[mcs] C# 7 tuple (foundation only).
authorMarek Safar <marek.safar@gmail.com>
Fri, 30 Jun 2017 17:44:41 +0000 (19:44 +0200)
committerMarek Safar <marek.safar@gmail.com>
Fri, 30 Jun 2017 17:47:06 +0000 (19:47 +0200)
Still couple of advanced features not implemented and parser cannot
deal with unnamed tuple type at type declaration level.

70 files changed:
mcs/class/Mono.CSharp/Mono.CSharp.dll.sources
mcs/errors/cs0029-38.cs [new file with mode: 0644]
mcs/errors/cs0815-7.cs [new file with mode: 0644]
mcs/errors/cs0826-11.cs [new file with mode: 0644]
mcs/errors/cs0828-7.cs [new file with mode: 0644]
mcs/errors/cs1026-2.cs [deleted file]
mcs/errors/cs1525-12.cs
mcs/errors/cs1525-40.cs
mcs/errors/cs1525-43.cs
mcs/errors/cs1525-57.cs [new file with mode: 0644]
mcs/errors/cs1525-7.cs
mcs/errors/cs1644-53.cs [new file with mode: 0644]
mcs/errors/cs1644-54.cs [new file with mode: 0644]
mcs/errors/cs8123-2.cs [new file with mode: 0644]
mcs/errors/cs8123.cs [new file with mode: 0644]
mcs/errors/cs8124.cs [new file with mode: 0644]
mcs/errors/cs8125.cs [new file with mode: 0644]
mcs/errors/cs8126.cs [new file with mode: 0644]
mcs/errors/cs8127.cs [new file with mode: 0644]
mcs/errors/cs8129.cs [new file with mode: 0644]
mcs/errors/cs8131.cs [new file with mode: 0644]
mcs/errors/cs8132.cs [new file with mode: 0644]
mcs/errors/cs8133.cs [new file with mode: 0644]
mcs/errors/cs8135.cs [new file with mode: 0644]
mcs/errors/cs8138.cs [new file with mode: 0644]
mcs/errors/cs8139-2.cs [new file with mode: 0644]
mcs/errors/cs8139-3.cs [new file with mode: 0644]
mcs/errors/cs8139-4.cs [new file with mode: 0644]
mcs/errors/cs8139.cs [new file with mode: 0644]
mcs/errors/cs8141-2.cs [new file with mode: 0644]
mcs/errors/cs8141.cs [new file with mode: 0644]
mcs/errors/cs8142.cs [new file with mode: 0644]
mcs/errors/cs8143.cs [new file with mode: 0644]
mcs/errors/cs8144.cs [new file with mode: 0644]
mcs/errors/cs8181.cs [new file with mode: 0644]
mcs/errors/cs8210.cs [new file with mode: 0644]
mcs/errors/cs8307.cs [new file with mode: 0644]
mcs/errors/known-issues-net_4_x
mcs/mcs/assign.cs
mcs/mcs/attribute.cs
mcs/mcs/class.cs
mcs/mcs/convert.cs
mcs/mcs/cs-parser.jay
mcs/mcs/cs-tokenizer.cs
mcs/mcs/decl.cs
mcs/mcs/delegate.cs
mcs/mcs/ecore.cs
mcs/mcs/expression.cs
mcs/mcs/field.cs
mcs/mcs/generic.cs
mcs/mcs/ikvm.cs
mcs/mcs/import.cs
mcs/mcs/mcs.csproj
mcs/mcs/mcs.exe.sources
mcs/mcs/membercache.cs
mcs/mcs/method.cs
mcs/mcs/parameter.cs
mcs/mcs/property.cs
mcs/mcs/report.cs
mcs/mcs/typemanager.cs
mcs/mcs/typespec.cs
mcs/tests/dtest-001.cs
mcs/tests/known-issues-net_4_x
mcs/tests/test-tuple-01.cs [new file with mode: 0644]
mcs/tests/test-tuple-02.cs [new file with mode: 0644]
mcs/tests/test-tuple-03.cs [new file with mode: 0644]
mcs/tests/test-tuple-04-lib.cs [new file with mode: 0644]
mcs/tests/test-tuple-04.cs [new file with mode: 0644]
mcs/tests/test-tuple-05.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_x.xml

index 041691b10992886422544d76b6ae350233a42e80..a9bdb1ad2c902a5c0b5c7628654bea4252993e96 100644 (file)
@@ -49,6 +49,7 @@ aot.cs
 ../../mcs/support.cs
 ../../mcs/typemanager.cs
 ../../mcs/typespec.cs
+../../mcs/tuples.cs
 ../../mcs/visit.cs
 ../../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
 ../../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
diff --git a/mcs/errors/cs0029-38.cs b/mcs/errors/cs0029-38.cs
new file mode 100644 (file)
index 0000000..6ee7146
--- /dev/null
@@ -0,0 +1,10 @@
+// CS0029: Cannot implicitly convert type `int' to `(long, bool)'
+// Line: 8
+
+class C
+{
+       static void Test ()
+       {
+               System.ValueTuple<long, bool> arg = 1;
+       }
+}
diff --git a/mcs/errors/cs0815-7.cs b/mcs/errors/cs0815-7.cs
new file mode 100644 (file)
index 0000000..38c3ff3
--- /dev/null
@@ -0,0 +1,10 @@
+// CS0815: An implicitly typed local variable declaration cannot be initialized with `(int, method group)'
+// Line: 8
+
+class XX
+{
+       public static void Main ()
+       {
+               var m = (1, Main);
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0826-11.cs b/mcs/errors/cs0826-11.cs
new file mode 100644 (file)
index 0000000..55d04ca
--- /dev/null
@@ -0,0 +1,10 @@
+// CS0826: The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly
+// Line: 8
+
+class XX
+{
+       public static void Main ()
+       {
+               var m = new [] { (1, Main) };
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0828-7.cs b/mcs/errors/cs0828-7.cs
new file mode 100644 (file)
index 0000000..c60a261
--- /dev/null
@@ -0,0 +1,12 @@
+// CS0827: An anonymous type property `Prop' cannot be initialized with `(int, method group)'
+// Line: 9
+
+class XX
+{
+       public static void Main ()
+       {
+               var m = new {
+                       Prop = (1, Main)
+               };
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs1026-2.cs b/mcs/errors/cs1026-2.cs
deleted file mode 100644 (file)
index 45dfd73..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// CS1026: Unexpected symbol `;', expecting `)'
-// Line: 10
-
-using System;
-
-class Test {
-        static void Main ()
-        {
-                string uri = "http://localhost/";
-                int default_port = (uri.StartsWith ("http://") ? 80 : -1;
-        }
-}
index a3b2eee19b60f5cf971befaa44493a37b49de0f5..47b4b4412a2e87bcf22ce816a5c6c7b4cc99dfaa 100644 (file)
@@ -1,4 +1,4 @@
-// CS1525: Unexpected symbol `==', expecting `type'
+// CS1525: Unexpected symbol `==', expecting `(' or `type'
 // Line: 8
 
 class A
index f7bac981094198fdca1f9c3d4bb5e519a6bfdcc4..297018f16bb3fe311fd154b4af4b07c318ca4053 100644 (file)
@@ -1,4 +1,4 @@
-// CS1525: Unexpected symbol `1', expecting `type'
+// CS1525: Unexpected symbol `1', expecting `(' or `type'
 // Line: 4
 
 class M : 1
index a43ae1ddb0a15e83038a8540e29d0e3e6f0dcf68..d83d4d847fadc538a6d2c9ff01b38d505b1a061d 100644 (file)
@@ -1,4 +1,4 @@
-// CS1525: Unexpected symbol `)', expecting `[', `out', `params', `ref', `this', or `type'
+// CS1525: Unexpected symbol `)', expecting `(', `[', `out', `params', `ref', `this', or `type'
 // Line: 6
 
 class TestClass
diff --git a/mcs/errors/cs1525-57.cs b/mcs/errors/cs1525-57.cs
new file mode 100644 (file)
index 0000000..4dd717a
--- /dev/null
@@ -0,0 +1,12 @@
+// CS1026: Unexpected symbol `;', expecting `)' or `,'
+// Line: 10
+
+using System;
+
+class Test {
+        static void Main ()
+        {
+                string uri = "http://localhost/";
+                int default_port = (uri.StartsWith ("http://") ? 80 : -1;
+        }
+}
index 9ac639029fdedf3cea84ada4d1437644d4a336f8..f28fd8ac7fa4b73029e3ac5f25ee46976153c3ab 100644 (file)
@@ -1,4 +1,4 @@
-// CS1525: Unexpected symbol `this', expecting `[', `{', or `type'
+// CS1525: Unexpected symbol `this', expecting `(', `[', `{', or `type'
 // Line: 8
 
 class M
diff --git a/mcs/errors/cs1644-53.cs b/mcs/errors/cs1644-53.cs
new file mode 100644 (file)
index 0000000..2c66dd0
--- /dev/null
@@ -0,0 +1,11 @@
+// CS1644: Feature `tuples' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 7
+// Compiler options: -langversion:6
+
+class Class
+{
+       static (int, bool) Foo ()
+       {
+               return;
+       }       
+}
diff --git a/mcs/errors/cs1644-54.cs b/mcs/errors/cs1644-54.cs
new file mode 100644 (file)
index 0000000..53d70f9
--- /dev/null
@@ -0,0 +1,11 @@
+// CS1644: Feature `tuples' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 9
+// Compiler options: -langversion:6
+
+class Class
+{
+       static void Main ()
+       {
+               var t = (a: 1, b: 2);
+       }       
+}
diff --git a/mcs/errors/cs8123-2.cs b/mcs/errors/cs8123-2.cs
new file mode 100644 (file)
index 0000000..4fe11ee
--- /dev/null
@@ -0,0 +1,11 @@
+// CS8123: The tuple element name `a' is ignored because a different name or no name is specified by the target type `(int, int)'
+// Line: 9
+// Compiler options: -warnaserror
+
+class C
+{
+       public static void Main ()
+       {
+               (int tt1, int tt2) t = (a: 1, 2);
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8123.cs b/mcs/errors/cs8123.cs
new file mode 100644 (file)
index 0000000..cf446b2
--- /dev/null
@@ -0,0 +1,11 @@
+// CS8123: The tuple element name `b' is ignored because a different name or no name is specified by the target type `(long, string)'
+// Line: 9
+// Compiler options: -warnaserror
+
+static class X
+{
+       static (long a, string x) Test ()
+       {
+               return (b: 1, "");
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8124.cs b/mcs/errors/cs8124.cs
new file mode 100644 (file)
index 0000000..d7d0416
--- /dev/null
@@ -0,0 +1,9 @@
+// CS8124: Tuple must contain at least two elements
+// Line: 6
+
+class X
+{
+       static (int) Foo ()
+       {
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8125.cs b/mcs/errors/cs8125.cs
new file mode 100644 (file)
index 0000000..bd45e59
--- /dev/null
@@ -0,0 +1,9 @@
+// CS8125: The tuple element name `Item22' can only be used at position 22
+// Line: 6
+
+class C
+{
+       static void Test ((int Item22, int b) arg)
+       {
+       }
+}
diff --git a/mcs/errors/cs8126.cs b/mcs/errors/cs8126.cs
new file mode 100644 (file)
index 0000000..67f4020
--- /dev/null
@@ -0,0 +1,9 @@
+// CS8126: The tuple element name `Rest' is reserved
+// Line: 6
+
+class C
+{
+       static void Test ((int Rest, int b) arg)
+       {
+       }
+}
diff --git a/mcs/errors/cs8127.cs b/mcs/errors/cs8127.cs
new file mode 100644 (file)
index 0000000..319dbf6
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8127: The tuple element name `a' is a duplicate
+// Line: 6
+
+class C
+{
+       static (int a, int a) Test ()
+       {
+               return null;
+       }
+}
diff --git a/mcs/errors/cs8129.cs b/mcs/errors/cs8129.cs
new file mode 100644 (file)
index 0000000..be6781b
--- /dev/null
@@ -0,0 +1,20 @@
+// CS8129:
+// Line:
+
+using System;
+
+class C
+{
+       static void Main ()
+       {
+               long x;
+               string y;
+               (x, y) = new C ();
+       }
+
+       public static void Deconstruct (out int a, out string b)
+       {
+               a = 1;
+               b = "hello";
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8131.cs b/mcs/errors/cs8131.cs
new file mode 100644 (file)
index 0000000..362c591
--- /dev/null
@@ -0,0 +1,11 @@
+// CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side
+// Line: 9
+
+class C
+{
+       public static void Main ()
+       {
+               int x, y;
+               (x, y) = null;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8132.cs b/mcs/errors/cs8132.cs
new file mode 100644 (file)
index 0000000..be9e522
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8132:
+// Line: 8
+
+class C
+{
+       public static void Main ()
+       {
+               var (t, u, v) = (1, 2);
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8133.cs b/mcs/errors/cs8133.cs
new file mode 100644 (file)
index 0000000..0c78125
--- /dev/null
@@ -0,0 +1,11 @@
+// CS8133: Cannot deconstruct dynamic objects
+// Line: 9
+
+class C
+{
+       public static void Test (dynamic d)
+       {
+               int x, y;
+               (x, y) = d;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8135.cs b/mcs/errors/cs8135.cs
new file mode 100644 (file)
index 0000000..797bcf5
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8135: Tuple literal `(int, method group)' cannot be converted to type `object'
+// Line: 8
+
+class XX
+{
+       public static void Main ()
+       {
+               object m = (1, Main);
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8138.cs b/mcs/errors/cs8138.cs
new file mode 100644 (file)
index 0000000..f870b72
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8138: Do not use `System.Runtime.CompilerServices.TupleElementNamesAttribute' directly. Use the tuple syntax instead
+// Line: 7
+
+using System;
+using System.Runtime.CompilerServices;
+
+[TupleElementNames (new[] { "a", "b" })]
+public class C
+{
+}
diff --git a/mcs/errors/cs8139-2.cs b/mcs/errors/cs8139-2.cs
new file mode 100644 (file)
index 0000000..93ff005
--- /dev/null
@@ -0,0 +1,18 @@
+// CS8139: `D.M()': cannot change return type tuple element names when overriding inherited member `C.M()'
+// Line: 14
+
+class C
+{
+       public virtual (int a, int b) M ()
+       {
+               throw null;
+       }
+}
+
+class D : C
+{
+       public override (int, int) M ()
+       {
+               throw null;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8139-3.cs b/mcs/errors/cs8139-3.cs
new file mode 100644 (file)
index 0000000..247a0d1
--- /dev/null
@@ -0,0 +1,16 @@
+// CS8139: `D.M((int, int))': cannot change tuple element names when overriding inherited member `C.M((int, int))'
+// Line: 13
+
+class C
+{
+       public virtual void M ((int, int) arg)
+       {
+       }
+}
+
+class D : C
+{
+       public override void M ((int c, int d) arg)
+       {
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8139-4.cs b/mcs/errors/cs8139-4.cs
new file mode 100644 (file)
index 0000000..8272a5d
--- /dev/null
@@ -0,0 +1,20 @@
+// CS8139: `D.Prop': cannot change return type tuple element names when overriding inherited member `C.Prop'
+// Line: 14
+
+class C
+{
+       public virtual (int a, int b) Prop {
+               get {
+                       throw null;
+               }
+       }
+}
+
+class D : C
+{
+       public override (int c, int d) Prop {
+               get {
+                       throw null;
+               }
+       }       
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8139.cs b/mcs/errors/cs8139.cs
new file mode 100644 (file)
index 0000000..cb49661
--- /dev/null
@@ -0,0 +1,18 @@
+// CS8139: `D.M()': cannot change return type tuple element names when overriding inherited member `C.M()'
+// Line: 14
+
+class C
+{
+       public virtual (int a, int b) M ()
+       {
+               throw null;
+       }
+}
+
+class D : C
+{
+       public override (int c, int d) M ()
+       {
+               throw null;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8141-2.cs b/mcs/errors/cs8141-2.cs
new file mode 100644 (file)
index 0000000..42c80ce
--- /dev/null
@@ -0,0 +1,19 @@
+// CS8141:
+// Line: 11
+
+public interface I<T>
+{
+       int this[T arg] { get; set; }
+}
+
+public class C : I<(int a, int b)>
+{
+       public int this[(int c, int d) arg] {
+               get {
+                       return 1;
+               }
+               set {
+
+               }
+       }
+}
diff --git a/mcs/errors/cs8141.cs b/mcs/errors/cs8141.cs
new file mode 100644 (file)
index 0000000..fd3c05f
--- /dev/null
@@ -0,0 +1,15 @@
+// CS8141:
+// Line: 9
+
+public interface I<T>
+{
+       T Test ();
+}
+
+public class C : I<(int a, int b)>
+{
+       public (int c, int d) Test ()
+       {
+               return (1, 2);
+       }
+}
diff --git a/mcs/errors/cs8142.cs b/mcs/errors/cs8142.cs
new file mode 100644 (file)
index 0000000..3a9fd35
--- /dev/null
@@ -0,0 +1,14 @@
+// CS8142: A partial method declaration and partial method implementation must both use the same tuple element names
+// Line: 11
+
+partial class X
+{
+       partial void Foo ((int a, int b) arg);
+}
+
+partial class X
+{
+       partial void Foo ((int c, int d) arg)
+       {
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8143.cs b/mcs/errors/cs8143.cs
new file mode 100644 (file)
index 0000000..19064cd
--- /dev/null
@@ -0,0 +1,13 @@
+// CS8143: An expression tree cannot contain a tuple literal
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       public static void Main ()
+       {
+               Expression<Func<object>> l = () => (-1, 2);
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8144.cs b/mcs/errors/cs8144.cs
new file mode 100644 (file)
index 0000000..4a5cc52
--- /dev/null
@@ -0,0 +1,14 @@
+// CS8144:
+// Line: 12
+
+using System;
+using System.Linq.Expressions;
+
+class X
+{
+       public static void Main ()
+       {
+               (byte b, short d) t = (0, 0);
+               Expression<Func<(int a, int aa)>> e = () => t;
+       }
+}
diff --git a/mcs/errors/cs8181.cs b/mcs/errors/cs8181.cs
new file mode 100644 (file)
index 0000000..523d168
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8181: Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead
+// Line: 8
+
+class C
+{
+       static void Main ()
+       {
+               var x = new (long, int) () {
+                       Item1 = 1
+               };
+       }
+}
diff --git a/mcs/errors/cs8210.cs b/mcs/errors/cs8210.cs
new file mode 100644 (file)
index 0000000..a297dc7
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8210: A tuple literal cannot not contain a value of type `void'
+// Line: 8
+
+class XX
+{
+       public static void Main ()
+       {
+               var m = (1, Main ());
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8307.cs b/mcs/errors/cs8307.cs
new file mode 100644 (file)
index 0000000..6772f50
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8307: The first operand of an `as' operator may not be a tuple literal without a natural type
+// Line: 8
+
+class X
+{
+       public static void Main ()
+       {
+               var g = (1, Main) as object;
+       }
+}
\ No newline at end of file
index 1e07f7c667ee0b12c339540088bf027700452b7b..9282fd4adb9ca50b0c36ae5f0994044de814604f 100644 (file)
@@ -17,3 +17,9 @@ cs0080.cs
 # Operators
 cs0457-2.cs
 cs0457.cs
+
+cs8129.cs NO ERROR
+cs8132.cs NO ERROR
+cs8141.cs
+cs8141-2.cs
+cs8144.cs
index 43399ffc3ae105be93bdbe212052714c7f7cde95..31231e6bf336f013a66dc7ce1b26cdbf9656e019 100644 (file)
@@ -390,6 +390,7 @@ namespace Mono.CSharp {
 
                        return System.Linq.Expressions.Expression.Assign (target_object, source_object);
                }
+
                protected virtual Expression ResolveConversions (ResolveContext ec)
                {
                        source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location);
index c1c28cd8eedded2fd694e782e6619a3d501ac13d..ca142609003dc480033ea2ae6be3e5182266453d 100644 (file)
@@ -258,6 +258,11 @@ namespace Mono.CSharp {
                        Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
                }
 
+               public void Error_MisusedTupleAttribute ()
+               {
+                       Report.Error (8138, loc, "Do not use `{0}' directly. Use the tuple syntax instead", GetSignatureForError ());
+               }
+
                void Error_AttributeEmitError (string inner)
                {
                        Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
@@ -1126,6 +1131,11 @@ namespace Mono.CSharp {
                        }
 
                        if (!IsConditionallyExcluded (ctor.DeclaringType)) {
+                               if (Type == predefined.TupleElementNames) {
+                                       Error_MisusedTupleAttribute ();
+                                       return;
+                               }
+
                                try {
                                        foreach (Attributable target in targets)
                                                target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
@@ -1742,6 +1752,9 @@ namespace Mono.CSharp {
                // New in .NET 4.5
                public readonly PredefinedStateMachineAttribute AsyncStateMachine;
 
+               // New in .NET 4.7
+               public readonly PredefinedTupleElementNamesAttribute TupleElementNames;
+
                //
                // Optional types which are used as types and for member lookup
                //
@@ -1821,6 +1834,8 @@ namespace Mono.CSharp {
                        CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
                        CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
 
+                       TupleElementNames = new PredefinedTupleElementNamesAttribute (module, "System.Runtime.CompilerServices", "TupleElementNamesAttribute");
+
                        // TODO: Should define only attributes which are used for comparison
                        const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
                                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
@@ -2171,4 +2186,83 @@ namespace Mono.CSharp {
                        return tctor != null;
                }
        }
+
+       public class PredefinedTupleElementNamesAttribute : PredefinedAttribute
+       {
+               MethodSpec tctor;
+
+               public PredefinedTupleElementNamesAttribute (ModuleContainer module, string ns, string name)
+                       : base (module, ns, name)
+               {
+               }
+
+               public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               CustomAttributeBuilder CreateCustomAttributeBuilder (TypeSpec type, Location loc)
+               {
+                       if (tctor == null) {
+                               tctor = module.PredefinedMembers.TupleElementNamesAttributeCtor.Resolve (loc);
+                               if (tctor == null)
+                                       return null;
+                       }
+
+                       var names = new List<string> (type.TypeArguments.Length);
+                       BuildStringElements (type, names);
+                       return new CustomAttributeBuilder ((ConstructorInfo)tctor.GetMetaInfo (), new object [] { names.ToArray () });
+               }
+
+               //
+               // Returns an array of names when any element of the type is
+               // tuple with named element. The array is built for top level
+               // type therefore it can contain multiple tuple types
+               //
+               // Example: Func<(int, int), int, (int a, int b)[]>
+               // Output: { null, null, "a", "b" }
+               //
+               static void BuildStringElements (TypeSpec type, List<string> names)
+               {
+                       while (type is ArrayContainer) {
+                               type = ((ArrayContainer)type).Element;
+                       }
+
+                       var nts = type as NamedTupleSpec;
+                       if (nts != null) {
+                               names.AddRange (nts.Elements);
+                       } else {
+                               for (int i = 0; i < type.Arity; ++i) {
+                                       names.Add (null);
+                               }
+                       }
+
+                       foreach (var ta in type.TypeArguments) {
+                               BuildStringElements (ta, names);
+                       }
+               }
+       }
 }
index ee417ec7ad5d2e297019767f451d0f61dde6f3e9..48b1c6921f3c897fe0b8e5780e59fe5f34a514aa 100644 (file)
@@ -2171,6 +2171,14 @@ namespace Mono.CSharp
 
                public override void Emit ()
                {
+                       if (Interfaces != null) {
+                               foreach (var iface in Interfaces) {
+                                       if (iface.HasNamedTupleElement) {
+                                               throw new NotImplementedException ("named tuples for .interfaceimpl");
+                                       }
+                               }
+                       }
+
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
@@ -2901,8 +2909,11 @@ namespace Mono.CSharp
                        if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
                                Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
 
-                       if (base_type != null && base_type.HasDynamicElement) {
-                               Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+                       if (base_type != null) {
+                               if (base_type.HasDynamicElement)
+                                       Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+                               if (base_type.HasNamedTupleElement)
+                                       Module.PredefinedAttributes.TupleElementNames.EmitAttribute (TypeBuilder, base_type, Location);
                        }
                }
 
@@ -3513,7 +3524,7 @@ namespace Mono.CSharp
                                ok = false;
                        }
 
-                       var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
+                       var base_member_type = ((IInterfaceMemberSpec)base_member).MemberType;
                        if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
                                Report.SymbolRelatedToPreviousError (base_member);
                                if (this is PropertyBasedMember) {
@@ -3524,6 +3535,20 @@ namespace Mono.CSharp
                                                GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
                                }
                                ok = false;
+                       } else if (!NamedTupleSpec.CheckOverrideName (MemberType, base_member_type)) {
+                               // CSC: Should be different error code
+                               Report.Error (8139, Location, "`{0}': cannot change return type tuple element names when overriding inherited member `{1}'",
+                                                         GetSignatureForError (), base_member.GetSignatureForError ());
+                               ok = false;
+                       }
+
+                       var base_params = base_member as IParametersMember;
+                       if (base_params != null) {
+                               if (!NamedTupleSpec.CheckOverrideName ((IParametersMember)this, base_params)) {
+                                       Report.Error (8139, Location, "`{0}': cannot change tuple element names when overriding inherited member `{1}'",
+                                                                 GetSignatureForError (), base_member.GetSignatureForError ());
+                                       ok = false;
+                               }
                        }
 
                        return ok;
index 3adb909e6f5afc782964f929c325165b6694813d..a99e3fde628b60061aae8448ab3621c23a7fad9c 100644 (file)
@@ -679,6 +679,80 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               static Expression ImplicitTupleLiteralConversion (ResolveContext rc, Expression source, TypeSpec targetType, Location loc)
+               {
+                       var targetTypeArgument = targetType.TypeArguments;
+                       if (source.Type.Arity != targetTypeArgument.Length)
+                               return null;
+
+                       var namedTarget = targetType as NamedTupleSpec;
+                       var tupleLiteral = source as TupleLiteral;
+                       Expression instance;
+
+                       if (tupleLiteral == null && !ExpressionAnalyzer.IsInexpensiveLoad (source)) {
+                               var expr_variable = LocalVariable.CreateCompilerGenerated (source.Type, rc.CurrentBlock, loc);
+                               source = new CompilerAssign (expr_variable.CreateReferenceExpression (rc, loc), source, loc);
+                               instance = expr_variable.CreateReferenceExpression (rc, loc);
+                       } else {
+                               instance = null;
+                       }
+
+                       var converted = new List<Expression> (targetType.Arity);
+                       for (int i = 0; i < targetType.Arity; ++i) {
+                               Expression elementSrc;
+                               if (tupleLiteral != null) {
+                                       elementSrc = tupleLiteral.Elements [i].Expr;
+
+                                       if (namedTarget != null) {
+                                               var elementSrcName = tupleLiteral.Elements [i].Name;
+                                               if (elementSrcName != null && elementSrcName != namedTarget.Elements [i]) {
+                                                       rc.Report.Warning (8123, 1, loc,
+                                                                          "The tuple element name `{0}' is ignored because a different name or no name is specified by the target type `{1}'",
+                                                                          elementSrcName, namedTarget.GetSignatureForErrorWithNames ());
+                                               }
+                                       }
+                               } else {
+                                       elementSrc = new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)).Resolve (rc);
+                               }
+
+                               var res = ImplicitConversionStandard (rc, elementSrc, targetTypeArgument [i], loc);
+                               if (res == null)
+                                       return null;
+
+                               converted.Add (res);
+                       }
+
+                       return new TupleLiteralConversion (source, targetType, converted, loc);
+               }
+
+               static bool ImplicitTupleLiteralConversionExists (Expression source, TypeSpec targetType)
+               {
+                       if (source.Type.Arity != targetType.Arity)
+                               return false;
+
+                       var srcTypeArgument = source.Type.TypeArguments;
+                       var targetTypeArgument = targetType.TypeArguments;
+
+                       var tupleLiteralElements = (source as TupleLiteral)?.Elements;
+
+                       for (int i = 0; i < targetType.Arity; ++i) {
+                               var elementType = srcTypeArgument [i];
+
+                               if (tupleLiteralElements != null) {
+                                       if (!ImplicitStandardConversionExists (tupleLiteralElements[i].Expr, targetTypeArgument [i])) {
+                                               return false;
+                                       }
+                               } else {
+                                       if (!ImplicitStandardConversionExists (new EmptyExpression (srcTypeArgument [i]), targetTypeArgument [i])) {
+                                               return false;
+                                       }
+                               }
+                       }
+
+                       return true;
+               }
+
+
                //
                // Full version of implicit conversion
                //
@@ -758,7 +832,10 @@ namespace Mono.CSharp {
 
                        if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
                                return true;
-                       
+
+                       if (expr_type.IsTupleType && target_type.IsTupleType)
+                               return ImplicitTupleLiteralConversionExists (expr, target_type);
+
                        //
                        // Implicit Constant Expression Conversions
                        //
@@ -1420,6 +1497,14 @@ namespace Mono.CSharp {
                                        return c;
                        }
 
+                       if (expr_type.IsTupleType) {
+                               if (target_type.IsTupleType)
+                                       return ImplicitTupleLiteralConversion (ec, expr, target_type, loc);
+
+                               if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (expr_type))
+                                       return null;
+                       }
+
                        e = ImplicitNumericConversion (expr, expr_type, target_type);
                        if (e != null)
                                return e;
@@ -1499,14 +1584,15 @@ namespace Mono.CSharp {
                ///   ImplicitConversion.  If there is no implicit conversion, then
                ///   an error is signaled
                /// </summary>
-               static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
+               public static Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
                                                                     TypeSpec target_type, Location loc)
                {
                        Expression e = ImplicitConversion (ec, source, target_type, loc);
                        if (e != null)
                                return e;
 
-                       source.Error_ValueCannotBeConverted (ec, target_type, false);
+                       if (target_type != InternalType.ErrorType)
+                               source.Error_ValueCannotBeConverted (ec, target_type, false);
 
                        return null;
                }
index 2df53e916640209092711ab75dee2489d0e8f64d..64652ccfcdad7e6f15f700c97b393608e04acad9 100644 (file)
@@ -335,6 +335,7 @@ namespace Mono.CSharp
 %token GENERIC_DIMENSION
 %token DEFAULT_COLON
 %token OPEN_BRACKET_EXPR
+%token OPEN_PARENS_DECONSTRUCT
 
 // Make the parser go into eval mode parsing (statements and compilation units).
 %token EVAL_STATEMENT_PARSER
@@ -927,7 +928,6 @@ named_argument
                $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, Argument.AType.Out);
                lbag.AddLocation ($$, GetLocation($2));
          }
-
        ;
 
 named_argument_expr
@@ -3239,6 +3239,52 @@ type_expression
                $$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2);
          }
        | builtin_type_expression
+       | OPEN_PARENS tuple_elements CLOSE_PARENS opt_nullable
+         {
+               if (lang_version < LanguageVersion.V_7)
+                       FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+               var a = (Tuple<TypeArguments, List<string>>) $2;
+               if (a.Item1.Count < 2) {
+                       report.Error (8124, GetLocation ($1), "Tuple must contain at least two elements");
+               }
+
+               $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+
+               if ($4 != null)
+                       $$ = new ComposedCast ((FullNamedExpression) $$, (ComposedTypeSpecifier) $4);
+         }
+       ;
+
+tuple_elements
+       : tuple_element tuple_element_name
+         {
+               var type_args = new TypeArguments ();
+               type_args.Add ((FullNamedExpression) $1);
+
+               var names = new List<string> (2);
+               var lt = (LocatedToken) $2;
+               names.Add (lt?.Value);
+
+               $$ = Tuple.Create (type_args, names);
+         }
+       | tuple_elements COMMA tuple_element tuple_element_name
+         {
+               var a = (Tuple<TypeArguments, List<string>>) $1;
+               a.Item1.Add ((FullNamedExpression) $3);
+               var lt = (LocatedToken) $4;
+               a.Item2.Add (lt?.Value);
+               $$ = a;
+         }
+       ;
+
+tuple_element_name
+       : /* empty */
+       | IDENTIFIER
+       ;
+
+tuple_element
+       : parameter_type
        ;
 
 void_invalid
@@ -3356,6 +3402,7 @@ type_name_expression
 
 literal
        : boolean_literal
+       | tuple_literal
        | LITERAL
        | NULL                  { $$ = new NullLiteral (GetLocation ($1)); }
        ;
@@ -3365,6 +3412,42 @@ boolean_literal
        | FALSE                 { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); }
        ;
 
+tuple_literal
+       : OPEN_PARENS tuple_literal_elements CLOSE_PARENS
+         {
+               if (lang_version < LanguageVersion.V_7)
+                       FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+               $$ = new TupleLiteral ((List<TupleLiteralElement>)$2, GetLocation ($1));
+         }
+       ;
+
+tuple_literal_elements
+       : tuple_literal_element COMMA tuple_literal_element
+         {
+               $$ = new List<TupleLiteralElement> () {
+                       (TupleLiteralElement) $1, (TupleLiteralElement) $3
+               };
+         }
+       | tuple_literal_elements COMMA tuple_literal_element
+         {
+               var list = (List<TupleLiteralElement>)$1;
+               list.Add ((TupleLiteralElement) $3);
+         }
+       ;
+
+tuple_literal_element
+       : expression
+         {
+               $$ = new TupleLiteralElement ((Expression) $1);
+         }
+       | IDENTIFIER COLON expression
+         {
+               var lt = (LocatedToken) $1;
+               $$ = new TupleLiteralElement (lt.Value, (Expression) $3, lt.Location);
+         }
+       ;
+
 interpolated_string
        : INTERPOLATED_STRING interpolations INTERPOLATED_STRING_END
          {
@@ -4391,7 +4474,6 @@ prefixed_unary_expression
 
                $$ = new Unary (Unary.Operator.AddressOf, null, GetLocation ($1));
          }
-       ;
 
 multiplicative_expression
        : prefixed_unary_expression
@@ -4535,16 +4617,18 @@ pattern_expr
          {
                $$ = new WildcardPattern (GetLocation ($1));
          }
-       | pattern_expr_invocation
+/*     | pattern_expr_invocation */
        | pattern_property
        ;
 
+/*
 pattern_expr_invocation
        : type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS
          {
                $$ = new RecursivePattern ((ATypeNameExpression) $1, (Arguments) $3, GetLocation ($2));
          }
        ;
+*/
 
 pattern_property
        : type_name_expression OPEN_BRACE pattern_property_list CLOSE_BRACE
@@ -4588,8 +4672,9 @@ pattern
          }
        ;
 
+/*
 opt_pattern_list
-       : /* empty */
+       : // empty
          {
                $$ = new Arguments (0);
          }
@@ -4614,6 +4699,7 @@ pattern_list
          }
        ;
 
+
 pattern_argument
        : pattern
          {
@@ -4625,6 +4711,7 @@ pattern_argument
                $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3);
          }
        ;
+*/
 
 shift_expression
        : additive_expression
@@ -4921,6 +5008,30 @@ assignment_expression
                $$ = new CompoundAssign (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3);
                lbag.AddLocation ($$, GetLocation ($2));
          }
+       | OPEN_PARENS_DECONSTRUCT deconstruct_exprs CLOSE_PARENS ASSIGN expression
+         {
+               if (lang_version < LanguageVersion.V_7)
+                       FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+               var exprs = (List<Expression>) $2;
+               $$ = new TupleDeconstruct (exprs, (Expression) $5, GetLocation ($4));
+         }
+       ;
+
+deconstruct_exprs
+       : expression COMMA expression
+         {
+               $$ = new List<Expression> () {
+                       (Expression) $1,
+                       (Expression) $3
+               };
+         }
+       | deconstruct_exprs COMMA expression
+         {
+               var src = (List<Expression>) $1;
+               src.Add ((Expression) $3);
+               $$ = src;
+         }
        ;
 
 lambda_parameter_list
@@ -5693,20 +5804,6 @@ variable_type
 variable_type_simple
        : type_name_expression opt_nullable
          { 
-               // Ok, the above "primary_expression" is there to get rid of
-               // both reduce/reduce and shift/reduces in the grammar, it should
-               // really just be "type_name".  If you use type_name, a reduce/reduce
-               // creeps up.  If you use namespace_or_type_name (which is all we need
-               // really) two shift/reduces appear.
-               // 
-
-               // So the super-trick is that primary_expression
-               // can only be either a SimpleName or a MemberAccess. 
-               // The MemberAccess case arises when you have a fully qualified type-name like :
-               // Foo.Bar.Blah i;
-               // SimpleName is when you have
-               // Blah i;
-               
                var expr = (ATypeNameExpression) $1;
                if ($2 == null) {
                        if (expr.Name == "var" && expr is SimpleName)
@@ -5723,9 +5820,54 @@ variable_type_simple
                $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2);
          }
        | builtin_type_expression
+       | tuple_type opt_nullable
+         {
+               if ($2 == null)
+                       $$ = $1;
+               else
+                       $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2);
+         }
        | void_invalid
        ;
-       
+
+tuple_type
+       : OPEN_PARENS tuple_type_elements CLOSE_PARENS
+         {
+               if (lang_version < LanguageVersion.V_7)
+                       FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+               var a = (Tuple<TypeArguments, List<string>>) $2;
+
+               $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+         }
+       ;
+
+tuple_type_elements
+       : variable_type IDENTIFIER /* opt_identifier */ COMMA variable_type IDENTIFIER /* opt_identifier */
+         {
+               var type_args = new TypeArguments ();
+
+               type_args.Add ((FullNamedExpression) $1);
+               type_args.Add ((FullNamedExpression) $4);
+
+               var names = new List<string> (2);
+               var lt = (LocatedToken) $2;
+               names.Add (lt?.Value);
+               lt = (LocatedToken) $5;
+               names.Add (lt?.Value);
+
+               $$ = Tuple.Create (type_args, names);
+         }
+       | tuple_type_elements COMMA variable_type IDENTIFIER /* opt_identifier */
+         {
+               var a = (Tuple<TypeArguments, List<string>>) $1;
+               a.Item1.Add ((FullNamedExpression) $3);
+               var lt = (LocatedToken) $4;
+               a.Item2.Add (lt?.Value);
+               $$ = a;
+         }
+       ;
+
 pointer_stars
        : pointer_star
        | pointer_star pointer_stars
@@ -8157,6 +8299,7 @@ static string GetTokenName (int token)
                return "]";
        case Token.OPEN_PARENS_CAST:
        case Token.OPEN_PARENS_LAMBDA:
+       case Token.OPEN_PARENS_DECONSTRUCT:
        case Token.OPEN_PARENS:
                return "(";
        case Token.CLOSE_PARENS:
index 1be3309b1bfdd611d404408e743e0414f81f2860..d6d00d31400f4d1f3777538d7e519066a1e19eac 100644 (file)
@@ -1027,7 +1027,7 @@ namespace Mono.CSharp
                }
 
                //
-               // Open parens micro parser. Detects both lambda and cast ambiguity.
+               // Open parens micro parser
                //      
                int TokenizeOpenParens ()
                {
@@ -1037,6 +1037,7 @@ namespace Mono.CSharp
                        int bracket_level = 0;
                        bool is_type = false;
                        bool can_be_type = false;
+                       bool at_least_one_comma = false;
                        
                        while (true) {
                                ptoken = current_token;
@@ -1052,6 +1053,12 @@ namespace Mono.CSharp
                                        if (current_token == Token.ARROW)
                                                return Token.OPEN_PARENS_LAMBDA;
 
+                                       //
+                                       // Expression inside parens is deconstruct expression, (a, x.y) = ...
+                                       //
+                                       if (current_token == Token.ASSIGN && at_least_one_comma)
+                                               return Token.OPEN_PARENS_DECONSTRUCT;
+
                                        //
                                        // Expression inside parens is single type, (int[])
                                        //
@@ -1164,6 +1171,7 @@ namespace Mono.CSharp
                                        if (bracket_level == 0) {
                                                bracket_level = 100;
                                                can_be_type = is_type = false;
+                                               at_least_one_comma = true;
                                        }
                                        continue;
 
@@ -1264,6 +1272,21 @@ namespace Mono.CSharp
                                }
 
                                return false;
+                       case Token.OPEN_PARENS:
+                               if (!parsing_generic_declaration)
+                                       return false;
+                               
+                               while (true) {
+                                       switch (token ()) {
+                                       case Token.COMMA:
+                                               // tuple declaration after <
+                                               return true;
+                                       case Token.OP_GENERICS_GT:
+                                       case Token.EOF:
+                                               return false;
+                                       }
+                               }
+
                        default:
                                return false;
                        }
@@ -3481,6 +3504,7 @@ namespace Mono.CSharp
                                                case Token.DEFAULT:
                                                case Token.DELEGATE:
                                                case Token.OP_GENERICS_GT:
+                                               case Token.REFVALUE:
                                                        return Token.OPEN_PARENS;
                                                }
 
index 0f0b1d1bb69749696d80b025d5da5bf27faf276b..b173b7b71fba74ac7c662715847f2825ba20c4ef 100644 (file)
@@ -926,6 +926,7 @@ namespace Mono.CSharp {
                        MissingDependency = 1 << 5,
                        HasDynamicElement = 1 << 6,
                        ConstraintsChecked = 1 << 7,
+                       HasNamedTupleElement = 1 << 8,
 
                        IsAccessor = 1 << 9,            // Method is an accessor
                        IsGeneric = 1 << 10,            // Member contains type arguments
@@ -942,6 +943,7 @@ namespace Mono.CSharp {
                        GenericIterateInterface = 1 << 21,
                        GenericTask = 1 << 22,
                        InterfacesImported = 1 << 23,
+                       Tuple = 1 << 24
                }
 
                //
@@ -951,7 +953,7 @@ namespace Mono.CSharp {
                        StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected |
                        StateFlags.Obsolete | StateFlags.Obsolete_Undetected |
                        StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected |
-                       StateFlags.HasDynamicElement;
+                       StateFlags.HasDynamicElement | StateFlags.HasNamedTupleElement;
 
                protected Modifiers modifiers;
                public StateFlags state;
index 4a0e4af6fc896df171530249f820649ebb8df0d5..368bb19c1b165d507f90e877ec40a5b993217093 100644 (file)
@@ -101,9 +101,7 @@ namespace Mono.CSharp {
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
                {
                        if (a.Target == AttributeTargets.ReturnValue) {
-                               if (return_attributes == null)
-                                       return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
-
+                               CreateReturnBuilder ();
                                return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
                                return;
                        }
@@ -122,6 +120,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               ReturnParameter CreateReturnBuilder ()
+               {
+                       return return_attributes ?? (return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location));
+               }
+
                protected override bool DoDefineMembers ()
                {
                        var builtin_types = Compiler.BuiltinTypes;
@@ -329,13 +332,16 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (ReturnType.Type != null) {
-                               if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
-                                       return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
-                                       Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
-                               } else if (ReturnType.Type.HasDynamicElement) {
-                                       return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
-                                       Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType.Type, Location);
+                       var rtype = ReturnType.Type;
+                       if (rtype != null) {
+                               if (rtype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
+                                       Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
+                               } else if (rtype.HasDynamicElement) {
+                                       Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, rtype, Location);
+                               }
+
+                               if (rtype.HasNamedTupleElement) {
+                                       Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, rtype, Location);
                                }
 
                                ConstraintChecker.Check (this, ReturnType.Type, ReturnType.Location);
index 73e50c4068f62902fd8f04dd4062e324366dd717..d15fbe5e34f6e9592987a466ff17580e9a95fbb9 100644 (file)
@@ -45,7 +45,7 @@ namespace Mono.CSharp {
                PropertyAccess,
                EventAccess,
                IndexerAccess,
-               Nothing, 
+               Nothing,
        }
 
        /// <remarks>
@@ -876,6 +876,15 @@ namespace Mono.CSharp {
                                        return MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
                        }
 
+                       if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+                               var ntuple = queried_type as NamedTupleSpec;
+                               if (ntuple != null) {
+                                       var ms = ntuple.FindElement (rc, name, loc);
+                                       if (ms != null)
+                                               return ExprClassFromMemberInfo (ms, loc);
+                               }
+                       }
+
                        return null;
                }
 
@@ -7798,13 +7807,14 @@ namespace Mono.CSharp {
                {
                }
 
-               public bool InferType (ResolveContext ec, Expression right_side)
+               public bool InferType (ResolveContext ec, Expression rhs)
                {
                        if (type != null)
                                throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
                        
-                       type = right_side.Type;
-                       if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
+                       type = rhs.Type;
+
+                       if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || (rhs is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
                                ec.Report.Error (815, loc,
                                        "An implicitly typed local variable declaration cannot be initialized with `{0}'",
                                        type.GetSignatureForError ());
index da37657867ed0e59f43a1d9eefdd010e977e9ae8..74f0aadd45b33f0f86b7ae297cb653f7a00cc1a3 100644 (file)
@@ -2420,6 +2420,12 @@ namespace Mono.CSharp
                        eclass = ExprClass.Value;
                        TypeSpec etype = expr.Type;
 
+                       if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (etype)) {
+                               ec.Report.Error (8307, expr.Location, "The first operand of an `as' operator may not be a tuple literal without a natural type");
+                               type = InternalType.ErrorType;
+                               return this;
+                       }
+
                        if (type == null) {
                                type = InternalType.ErrorType;
                                return this;
@@ -7108,6 +7114,16 @@ namespace Mono.CSharp
                        return DoResolveInvocation (rc);
                }
 
+               public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+               {
+                       var sn = expr as SimpleName;
+                       if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
+                               throw new NotImplementedException ("var deconstruct");
+                       }
+
+                       return base.DoResolveLValue (rc, right_side);
+               }
+
                Expression DoResolveInvocation (ResolveContext ec)
                {
                        Expression member_expr;
@@ -7504,6 +7520,10 @@ namespace Mono.CSharp
                
                protected override Expression DoResolve (ResolveContext ec)
                {
+                       if (RequestedType is TupleTypeExpr) {
+                               ec.Report.Error (8181, loc, "Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead.");
+                       }
+
                        type = RequestedType.ResolveAsType (ec);
                        if (type == null)
                                return null;
@@ -8668,9 +8688,7 @@ namespace Mono.CSharp
                        array_element_type = best_type_inference.InferredTypeArguments[0];
                        best_type_inference = null;
 
-                       if (array_element_type == null ||
-                               array_element_type == InternalType.NullLiteral || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
-                               arguments.Count != rank.Dimension) {
+                       if (array_element_type == null || InternalType.HasNoType (array_element_type) || arguments.Count != rank.Dimension) {
                                ec.Report.Error (826, loc,
                                        "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
                                return null;
@@ -12563,7 +12581,7 @@ namespace Mono.CSharp
                        }
 
                        type = e.Type;
-                       if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
+                       if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || type.IsPointer || (e is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
                                Error_InvalidInitializer (ec, type.GetSignatureForError ());
                                return null;
                        }
index 3528e8c5fbda2ccb32eaf41a8b1069398e375a6a..da337a8261ab40ed86f89ad0d63b53e2aec3c2cc 100644 (file)
@@ -244,6 +244,10 @@ namespace Mono.CSharp
                                Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location);
                        }
 
+                       if (member_type.HasNamedTupleElement) {
+                               Module.PredefinedAttributes.TupleElementNames.EmitAttribute (FieldBuilder, member_type, Location);
+                       }
+
                        if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
                                Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder);
                        if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
@@ -312,7 +316,7 @@ namespace Mono.CSharp
                        }
                }
 
-#endregion
+               #endregion
 
                public FieldInfo GetMetaInfo ()
                {
index 6b35de9846c6ba3d0be116b321af98c721297926..1efba64ba575caf08f33deae99bafc47c5fc4e3f 100644 (file)
@@ -1772,7 +1772,10 @@ namespace Mono.CSharp {
                        foreach (var arg in targs) {
                                if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
                                        state |= StateFlags.HasDynamicElement;
-                                       break;
+                               }
+
+                               if (arg.HasNamedTupleElement) {
+                                       state |= StateFlags.HasNamedTupleElement;
                                }
                        }
 
@@ -1852,6 +1855,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override bool IsTupleType {
+                       get {
+                               return (open_type.state & StateFlags.Tuple) != 0;
+                       }
+               }
+
                //
                // Types used to inflate the generic  type
                //
@@ -3095,6 +3104,9 @@ namespace Mono.CSharp {
                            bound.Type == InternalType.ThrowExpr)
                                return;
 
+                       if (bound.Type.IsTupleType && TupleLiteral.ContainsNoTypeElement (bound.Type))
+                               return;
+
                        var a = bounds [index];
                        if (a == null) {
                                a = new List<BoundInfo> (2);
index 62f671e1d101720421a10270a7dbcc929e0752c1..6724f8da5573aecf054d4c6d7a2e97f5770b0995 100644 (file)
@@ -134,7 +134,7 @@ namespace Mono.CSharp
                                if (t.Name[0] == '<')
                                        continue;
 
-                               var it = CreateType (t, null, new DynamicTypeReader (t), true);
+                               var it = CreateType (t, null, new AttributesTypeInfoReader (t), true);
                                if (it == null)
                                        continue;
 
index dbec2c0469f603bce116c228d4a3252b2abc85be..719ba23952cd714f0021ef68335b081af7a94640 100644 (file)
@@ -30,15 +30,18 @@ namespace Mono.CSharp
        public abstract class MetadataImporter
        {
                //
-               // Dynamic types reader with additional logic to reconstruct a dynamic
-               // type using DynamicAttribute values
+               // Types reader with additional logic to reconstruct extra
+               // type information encoded in custom attributes values
                //
-               protected struct DynamicTypeReader
+               protected struct AttributesTypeInfoReader
                {
                        static readonly bool[] single_attribute = { true };
 
-                       public int Position;
-                       bool[] flags;
+                       public int DynamicPosition;
+                       bool[] dynamicFlags;
+
+                       public int TuplePosition;
+                       string[] tupleNames;
 
                        // There is no common type for CustomAttributeData and we cannot
                        // use ICustomAttributeProvider
@@ -47,10 +50,12 @@ namespace Mono.CSharp
                        //
                        // A member provider which can be used to get CustomAttributeData
                        //
-                       public DynamicTypeReader (object provider)
+                       public AttributesTypeInfoReader (object provider)
                        {
-                               Position = 0;
-                               flags = null;
+                               DynamicPosition = 0;
+                               TuplePosition = 0;
+                               dynamicFlags = null;
+                               tupleNames = null;
                                this.provider = provider;
                        }
 
@@ -62,7 +67,7 @@ namespace Mono.CSharp
                                if (provider != null)
                                        ReadAttribute ();
 
-                               return flags != null && Position < flags.Length && flags[Position];
+                               return dynamicFlags != null && DynamicPosition < dynamicFlags.Length && dynamicFlags [DynamicPosition];
                        }
 
                        //
@@ -73,7 +78,34 @@ namespace Mono.CSharp
                                if (provider != null)
                                        ReadAttribute ();
 
-                               return flags != null;
+                               return dynamicFlags != null;
+                       }
+
+                       public bool HasNamedTupleAttribute ()
+                       {
+                               if (provider != null)
+                                       ReadAttribute ();
+
+                               return tupleNames != null;
+                       }
+
+                       public IList<string> GetNamedTupleElements (int length)
+                       {
+                               if (TuplePosition == 0 && length == tupleNames.Length)
+                                       return tupleNames;
+
+                               for (int i = TuplePosition; i < length + TuplePosition; ++i) {
+                                       if (tupleNames [i] != null) {
+                                               var res = new string [length];
+                                               Array.Copy (tupleNames, TuplePosition, res, 0, length);
+                                               return res;
+                                       }
+                               }
+
+                               //
+                               // Current range can be just padding
+                               //
+                               return null;
                        }
 
                        IList<CustomAttributeData> GetCustomAttributes ()
@@ -100,22 +132,40 @@ namespace Mono.CSharp
                                if (cad.Count > 0) {
                                        foreach (var ca in cad) {
                                                var dt = ca.Constructor.DeclaringType;
-                                               if (dt.Name != "DynamicAttribute" || dt.Namespace != CompilerServicesNamespace)
+                                               if (dt.Namespace != CompilerServicesNamespace)
                                                        continue;
 
-                                               if (ca.ConstructorArguments.Count == 0) {
-                                                       flags = single_attribute;
-                                                       break;
-                                               }
+                                               switch (dt.Name) {
+                                               case "DynamicAttribute":
+                                                       if (ca.ConstructorArguments.Count == 0) {
+                                                               dynamicFlags = single_attribute;
+                                                               break;
+                                                       }
 
-                                               var arg_type = ca.ConstructorArguments[0].ArgumentType;
+                                                       var arg_type = ca.ConstructorArguments [0].ArgumentType;
 
-                                               if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
-                                                       var carg = (IList<CustomAttributeTypedArgument>) ca.ConstructorArguments[0].Value;
-                                                       flags = new bool[carg.Count];
-                                                       for (int i = 0; i < flags.Length; ++i) {
-                                                               if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean)
-                                                                       flags[i] = (bool) carg[i].Value;
+                                                       if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
+                                                               var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+                                                               dynamicFlags = new bool [carg.Count];
+                                                               for (int i = 0; i < dynamicFlags.Length; ++i) {
+                                                                       if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.Boolean)
+                                                                               dynamicFlags [i] = (bool)carg [i].Value;
+                                                               }
+                                                       }
+
+                                                       break;
+                                               case "TupleElementNamesAttribute":
+                                                       if (ca.ConstructorArguments.Count != 1)
+                                                               break;
+
+                                                       var tuple_arg_type = ca.ConstructorArguments [0].ArgumentType;
+                                                       if (tuple_arg_type.IsArray && MetaType.GetTypeCode (tuple_arg_type.GetElementType ()) == TypeCode.String) {
+                                                               var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+                                                               tupleNames = new string [carg.Count];
+                                                               for (int i = 0; i < tupleNames.Length; ++i) {
+                                                                       if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.String)
+                                                                               tupleNames [i] = (string)carg [i].Value;
+                                                               }
                                                        }
 
                                                        break;
@@ -195,7 +245,7 @@ namespace Mono.CSharp
                        TypeSpec field_type;
 
                        try {
-                               field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi), declaringType);
+                               field_type = ImportType (fi.FieldType, new AttributesTypeInfoReader (fi), declaringType);
 
                                //
                                // Private field has private type which is not fixed buffer
@@ -275,7 +325,7 @@ namespace Mono.CSharp
                        if (add.Modifiers != remove.Modifiers)
                                throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
 
-                       var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei), declaringType);
+                       var event_type = ImportType (ei.EventHandlerType, new AttributesTypeInfoReader (ei), declaringType);
                        var definition = new ImportedMemberDefinition (ei, event_type,  this);
                        return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove);
                }
@@ -327,15 +377,15 @@ namespace Mono.CSharp
                                var type = tparams[pos];
                                int index = pos - first;
 
-                               tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false);
+                               tspec[index] = (TypeParameterSpec) CreateType (type, new AttributesTypeInfoReader (), false);
                        }
 
                        return tspec;
                }
 
-               TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype)
+               TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, AttributesTypeInfoReader dtype)
                {
-                       ++dtype.Position;
+                       ++dtype.DynamicPosition;
 
                        var tspec = new TypeSpec [tparams.Length - first];
                        for (int pos = first; pos < tparams.Length; ++pos) {
@@ -345,7 +395,7 @@ namespace Mono.CSharp
                                TypeSpec spec;
                                if (type.HasElementType) {
                                        var element = type.GetElementType ();
-                                       ++dtype.Position;
+                                       ++dtype.DynamicPosition;
                                        spec = ImportType (element, dtype, null);
 
                                        if (!type.IsArray) {
@@ -374,7 +424,7 @@ namespace Mono.CSharp
                                if (spec == null)
                                        return null;
 
-                               ++dtype.Position;
+                               ++dtype.DynamicPosition;
                                tspec[index] = spec;
                        }
 
@@ -415,7 +465,7 @@ namespace Mono.CSharp
                                returnType = module.Compiler.BuiltinTypes.Void;
                        } else {
                                var mi = (MethodInfo)mb;
-                               returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter), declaringType);
+                               returnType = ImportType (mi.ReturnType, new AttributesTypeInfoReader (mi.ReturnParameter), declaringType);
 
                                //
                                // Detect operators and destructors
@@ -545,13 +595,13 @@ namespace Mono.CSharp
                                        // Strip reference wrapping
                                        //
                                        var el = p.ParameterType.GetElementType ();
-                                       types[i] = ImportType (el, new DynamicTypeReader (p), parent);  // TODO: 1-based positio to be csc compatible
+                                       types[i] = ImportType (el, new AttributesTypeInfoReader (p), parent);   // TODO: 1-based positio to be csc compatible
                                } else if (i == 0 && method.IsStatic && (parent.Modifiers & Modifiers.METHOD_EXTENSION) != 0 &&
                                        HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
                                        mod = Parameter.Modifier.This;
-                                       types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+                                       types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
                                } else {
-                                       types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+                                       types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
 
                                        if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
                                                if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
@@ -734,26 +784,26 @@ namespace Mono.CSharp
 
                public TypeSpec CreateType (MetaType type)
                {
-                       return CreateType (type, new DynamicTypeReader (), true);
+                       return CreateType (type, new AttributesTypeInfoReader (), true);
                }
 
                public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType)
                {
-                       return CreateType (type, declaringType, new DynamicTypeReader (type), false);
+                       return CreateType (type, declaringType, new AttributesTypeInfoReader (type), false);
                }
 
-               TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType)
+               TypeSpec CreateType (MetaType type, AttributesTypeInfoReader dtype, bool canImportBaseType)
                {
                        TypeSpec declaring_type;
                        if (type.IsNested && !type.IsGenericParameter)
-                               declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true);
+                               declaring_type = CreateType (type.DeclaringType, new AttributesTypeInfoReader (type.DeclaringType), true);
                        else
                                declaring_type = null;
 
                        return CreateType (type, declaring_type, dtype, canImportBaseType);
                }
 
-               protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType)
+               protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, AttributesTypeInfoReader dtype, bool canImportBaseType)
                {
                        TypeSpec spec;
                        if (import_cache.TryGetValue (type, out spec)) {
@@ -796,7 +846,7 @@ namespace Mono.CSharp
                                        return null;
                                if (declaringType == null) {
                                        // Simple case, no nesting
-                                       spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
+                                       spec = CreateType (type_def, null, new AttributesTypeInfoReader (), canImportBaseType);
                                        spec = spec.MakeGenericType (module, targs);
                                } else {
                                        //
@@ -851,6 +901,14 @@ namespace Mono.CSharp
                                        }
                                }
 
+                               if (spec.IsTupleType && dtype.HasNamedTupleAttribute ()) {
+                                       var names = dtype.GetNamedTupleElements (spec.Arity);
+                                       if (names != null)
+                                               return NamedTupleSpec.MakeType (module, (InflatedTypeSpec) spec, names);
+
+                                       dtype.TuplePosition += spec.Arity;
+                               }
+
                                // Don't add generic type with dynamic arguments, they can interfere with same type
                                // using object type arguments
                                if (!spec.HasDynamicElement) {
@@ -1071,7 +1129,7 @@ namespace Mono.CSharp
                        else if (type.BaseType != null) {
                                TypeSpec base_type;
                                if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType)
-                                       base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true);
+                                       base_type = CreateType (type.BaseType, new AttributesTypeInfoReader (type), true);
                                else
                                        base_type = CreateType (type.BaseType);
 
@@ -1100,7 +1158,7 @@ namespace Mono.CSharp
                                if (t.Name[0] == '<')
                                        continue;
 
-                               var it = CreateType (t, null, new DynamicTypeReader (t), true);
+                               var it = CreateType (t, null, new AttributesTypeInfoReader (t), true);
                                if (it == null)
                                        continue;
 
@@ -1192,14 +1250,14 @@ namespace Mono.CSharp
 
                public TypeSpec ImportType (MetaType type)
                {
-                       return ImportType (type, new DynamicTypeReader (type), null);
+                       return ImportType (type, new AttributesTypeInfoReader (type), null);
                }
 
-               TypeSpec ImportType (MetaType type, DynamicTypeReader dtype, TypeSpec currentType)
+               TypeSpec ImportType (MetaType type, AttributesTypeInfoReader dtype, TypeSpec currentType)
                {
                        if (type.HasElementType) {
                                var element = type.GetElementType ();
-                               ++dtype.Position;
+                               ++dtype.DynamicPosition;
                                var spec = ImportType (element, dtype, currentType);
 
                                if (type.IsArray)
index 74a217c4eb22d0c0491626502091d0b053a243f5..de5655e7e4d86aed597661d669bdc79dec7bfc60 100644 (file)
     <Compile Include="field.cs" />\r
     <Compile Include="typespec.cs" />\r
     <Compile Include="visit.cs" />\r
+    <Compile Include="tuples.cs" />\r
   </ItemGroup>\r
   <ItemGroup Label="IKVM.Reflection">\r
     <Compile Include="..\..\external\ikvm\reflect\*.cs">\r
index dec804804cb83cf64747d4e8f9807ce2ac2f1151..b74a8fdac793ba0a01a4e8c0789014c6d98a5c9f 100644 (file)
@@ -49,6 +49,7 @@ statement.cs
 support.cs
 typemanager.cs
 typespec.cs
+tuples.cs
 visit.cs
 ../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
 ../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
index 48f5f09c7047e903979cd61343b77948d945e162..d132c872bafced81c59fd1eaf5bc8fd8245eb9a1 100644 (file)
@@ -1501,6 +1501,12 @@ namespace Mono.CSharp {
                                                        }
                                                        return false;
                                                }
+
+                                               var pm_member = (MethodCore)member;
+                                               if (!NamedTupleSpec.CheckOverrideName (pm, pm_member) || !NamedTupleSpec.CheckOverrideName (pm.MemberType, pm_member.MemberType)) {
+                                                       Report.Error (8142, member.Location,
+                                                               "A partial method declaration and partial method implementation must both use the same tuple element names");
+                                               }
                                        }
                                }
 
index c2b993564e2b354b066ca651e60f816da3707d00..ccd4898e91c7a5ef5169a3460c462ea429e8f38f 100644 (file)
@@ -558,10 +558,7 @@ namespace Mono.CSharp {
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
                {
                        if (a.Target == AttributeTargets.ReturnValue) {
-                               if (return_attributes == null)
-                                       return_attributes = new ReturnParameter (this, MethodBuilder, Location);
-
-                               return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
+                               CreateReturnBuilder ().ApplyAttributeBuilder (a, ctor, cdata, pa);
                                return;
                        }
 
@@ -624,6 +621,11 @@ namespace Mono.CSharp {
                        return new EmitContext (this, ig, MemberType, sourceMethod);
                }
 
+               ReturnParameter CreateReturnBuilder ()
+               {
+                       return return_attributes ?? (return_attributes = new ReturnParameter (this, MethodBuilder, Location));
+               }
+
                public override bool Define ()
                {
                        if (!base.Define ())
@@ -655,7 +657,7 @@ namespace Mono.CSharp {
 
                                explicit_name = null;
                        } else {
-                               MethodData = new MethodData (this, ModFlags, flags, this, base_method);
+                               MethodData = new MethodData (this, ModFlags, flags, this);
 
                                if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
                                        return false;
@@ -711,11 +713,13 @@ namespace Mono.CSharp {
                                Module.PredefinedAttributes.DebuggerStepThrough.EmitAttribute (MethodBuilder);
 
                        if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
-                               return_attributes = new ReturnParameter (this, MethodBuilder, Location);
-                               Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
                        } else if (ReturnType.HasDynamicElement) {
-                               return_attributes = new ReturnParameter (this, MethodBuilder, Location);
-                               Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
+                       }
+
+                       if (ReturnType.HasNamedTupleElement) {
+                               Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
                        }
 
                        if (OptAttributes != null)
@@ -1947,7 +1951,6 @@ namespace Mono.CSharp {
                protected Modifiers modifiers;
                protected MethodAttributes flags;
                protected TypeSpec declaring_type;
-               protected MethodSpec parent_method;
                SourceMethodBuilder debug_builder;
                string full_name;
 
@@ -1980,15 +1983,6 @@ namespace Mono.CSharp {
                        this.method = method;
                }
 
-               public MethodData (InterfaceMemberBase member,
-                                  Modifiers modifiers, MethodAttributes flags, 
-                                  IMethodData method,
-                                  MethodSpec parent_method)
-                       : this (member, modifiers, flags, method)
-               {
-                       this.parent_method = parent_method;
-               }
-
                public bool Define (TypeDefinition container, string method_full_name)
                {
                        PendingImplementation pending = container.PendingImplementations;
@@ -2045,6 +2039,20 @@ namespace Mono.CSharp {
                                                                }
                                                        }
                                                }
+
+                                               if (!NamedTupleSpec.CheckOverrideName (member.MemberType, implementing.ReturnType)) {
+                                                       container.Compiler.Report.Error (8141, method.Location,
+                                                               "The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
+                                                               member.GetSignatureForError (), implementing.GetSignatureForError ());
+                                               }
+
+                                               var p_member = method as IParametersMember;
+                                               var p_implementing = implementing as IParametersMember;
+                                               if (p_member != null && p_implementing != null && !NamedTupleSpec.CheckOverrideName (p_member, p_implementing)) {
+                                                       container.Compiler.Report.Error (8141, method.Location,
+                                                               "The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
+                                                               member.GetSignatureForError (), implementing.GetSignatureForError ());
+                                               }
                                        }
                                }
                        } else {
@@ -2073,7 +2081,7 @@ namespace Mono.CSharp {
                                        }
                                } else {
                                        //
-                                       // Setting implementin to null inside this block will trigger a more
+                                       // Setting implementing to null inside this block will trigger a more
                                        // verbose error reporting for missing interface implementations
                                        //
                                        if (implementing.DeclaringType.IsInterface) {
@@ -2422,9 +2430,7 @@ namespace Mono.CSharp {
                        }
 
                        if (a.Target == AttributeTargets.ReturnValue) {
-                               if (return_attributes == null)
-                                       return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
-
+                               CreateReturnBuilder ();
                                return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
                                return;
                        }
@@ -2443,6 +2449,11 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ();
                }
 
+               ReturnParameter CreateReturnBuilder ()
+               {
+                       return return_attributes ?? (return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location));
+               }
+
                public virtual void Emit (TypeDefinition parent)
                {
                        method_data.Emit (parent);
@@ -2453,11 +2464,13 @@ namespace Mono.CSharp {
                                Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
 
                        if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
-                               return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
-                               Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
                        } else if (ReturnType.HasDynamicElement) {
-                               return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
-                               Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
+                       }
+
+                       if (ReturnType.HasNamedTupleElement) {
+                               Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
                        }
 
                        if (OptAttributes != null)
index 1360dbdfd65c3cc4144c8e26b052c4fb200e796f..2bd2a498a919444a5862a395038f7d42e5500862 100644 (file)
@@ -726,6 +726,10 @@ namespace Mono.CSharp {
                                } else if (parameter_type.HasDynamicElement) {
                                        pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
                                }
+
+                               if (parameter_type.HasNamedTupleElement) {
+                                       pa.TupleElementNames.EmitAttribute (builder, parameter_type, Location);
+                               }
                        }
                }
 
index 0d4efedbd1e6465e4df5f4e50eaa67e07e86db7b..1dd8a86468eb1ab0f2727a649f67d3273ed6d8cd 100644 (file)
@@ -680,6 +680,10 @@ namespace Mono.CSharp
                                Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
                        }
 
+                       if (member_type.HasNamedTupleElement) {
+                               Module.PredefinedAttributes.TupleElementNames.EmitAttribute (PropertyBuilder, member_type, Location);
+                       }
+
                        ConstraintChecker.Check (this, member_type, type_expr.Location);
 
                        first.Emit (Parent);
index f73bed2b0b0d6b342ceb69dcc362bc54e06adf8e..cc3d82b26e0bd17639baf9a4034d871fe5e24de6 100644 (file)
@@ -58,7 +58,7 @@ namespace Mono.CSharp {
                        3021, 3022, 3023, 3024, 3026, 3027,
                        4014, 4024, 4025, 4026,
                        7035, 7080, 7081, 7082, 7095,
-                       8009, 8094
+                       8009, 8094, 8123
                };
 
                public Report (CompilerContext context, ReportPrinter printer)
index b53915f6eb1c030c749d98c239553e8a7c46c76d..b6aff14e1c025195c5ec8425d623610361c19ae9 100644 (file)
@@ -240,6 +240,9 @@ namespace Mono.CSharp
                public readonly PredefinedType FormattableString;
                public readonly PredefinedType FormattableStringFactory;
 
+               // C# 7.0
+               public readonly PredefinedType[] Tuples;
+
                public PredefinedTypes (ModuleContainer module)
                {
                        TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
@@ -337,6 +340,14 @@ namespace Mono.CSharp
 
                        IFormattable.Define ();
                        FormattableString.Define ();
+
+                       Tuples = new PredefinedType [8];
+                       for (int i = 0; i < Tuples.Length; i++) {
+                               var pt = new PredefinedType (module, MemberKind.Struct, "System", "ValueTuple", i + 1);
+                               Tuples [i] = pt;
+                               if (pt.Define ())
+                                       pt.TypeSpec.IsTupleType = true;
+                       }
                }
        }
 
@@ -403,6 +414,7 @@ namespace Mono.CSharp
                public readonly PredefinedMember<FieldSpec> StructLayoutCharSet;
                public readonly PredefinedMember<FieldSpec> StructLayoutSize;
                public readonly PredefinedMember<MethodSpec> TypeGetTypeFromHandle;
+               public readonly PredefinedMember<MethodSpec> TupleElementNamesAttributeCtor;
 
                public PredefinedMembers (ModuleContainer module)
                {
@@ -715,6 +727,10 @@ namespace Mono.CSharp
                                MemberFilter.Field ("Size", btypes.Int));
 
                        TypeGetTypeFromHandle = new PredefinedMember<MethodSpec> (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle);
+
+                       TupleElementNamesAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.TupleElementNames,
+                               MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
+                                       ArrayContainer.MakeType (module, btypes.String))));
                }
        }
 
index 53402940dc2dda5959bc5d925cefe29d0701d40c..e6ee60c585a8780e1af95af20b7941356d0a160b 100644 (file)
@@ -92,6 +92,12 @@ namespace Mono.CSharp
                        }
                }
 
+               public bool HasNamedTupleElement {
+                       get {
+                               return (state & StateFlags.HasNamedTupleElement) != 0;
+                       }
+               }
+
                //
                // Returns a list of all interfaces including
                // interfaces from base type or base interfaces
@@ -231,6 +237,18 @@ namespace Mono.CSharp
                        }
                }
 
+               //
+               // Returns true for instances of any System.ValueTuple<......> type
+               //
+               public virtual bool IsTupleType {
+                       get {
+                               return (state & StateFlags.Tuple) != 0;
+                       }
+                       set {
+                               state = value ? state | StateFlags.Tuple : state & ~StateFlags.Tuple;
+                       }
+               }
+
                // TODO: Should probably do
                // IsGenericType -- recursive
                // HasTypeParameter -- non-recursive
@@ -533,7 +551,9 @@ namespace Mono.CSharp
                        if (IsNested) {
                                s = DeclaringType.GetSignatureForError ();
                        } else if (MemberDefinition is AnonymousTypeClass) {
-                               return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
+                               return ((AnonymousTypeClass)MemberDefinition).GetSignatureForError ();
+                       } else if (IsTupleType) {
+                               return FormatTupleSignature ();
                        } else {
                                s = MemberDefinition.Namespace;
                        }
@@ -544,6 +564,21 @@ namespace Mono.CSharp
                        return s + Name + GetTypeNameSignature ();
                }
 
+               string FormatTupleSignature ()
+               {
+                       var sb = new StringBuilder ();
+                       sb.Append ("(");
+                       for (int i = 0; i < TypeArguments.Length; ++i) {
+                               if (i != 0)
+                                       sb.Append (", ");
+
+                               sb.Append (TypeArguments[i].GetSignatureForError ());
+                       }
+                       sb.Append (")");
+
+                       return sb.ToString ();
+               }
+
                public string GetSignatureForErrorIncludingAssemblyName ()
                {
                        var imported = MemberDefinition.DeclaringAssembly as ImportedAssemblyDefinition;
@@ -1574,6 +1609,11 @@ namespace Mono.CSharp
                }
 
                #endregion
+
+               public static bool HasNoType (TypeSpec type)
+               {
+                       return type == AnonymousMethod || type == MethodGroup || type == NullLiteral || type == ThrowExpr;
+               }
        }
 
        //
index f0b58ef8b9a0758ad265a412d9b0cb85b601ff7a..78de1d8253d0238728d07127d8fd5d831fe27c7b 100644 (file)
@@ -12,7 +12,11 @@ interface I<T>
 {
 }
 
-class C
+class B<T>
+{
+}
+
+class C : B<dynamic>
 {
        public C (dynamic d)
        {
@@ -108,6 +112,9 @@ class Test
                if (t.GetConstructors ()[0].GetCustomAttributes (ca, false).Length != 0)
                        return 21;
 
+               if (t.GetCustomAttributes (ca, false).Length != 1)
+                       return 22;
+
                // Transformations
                DynamicAttribute da;
                da = t.GetMember ("t")[0].GetCustomAttributes (ca, false)[0] as DynamicAttribute;
index eac11ac15f91607127af3ecdd47cab1e7ce9215f..2d15eafa2a329343d81d9d4e4652e993e3c2b2d7 100644 (file)
@@ -6,3 +6,6 @@
 
 gtest-230.cs
 test-pattern-02.cs
+test-pattern-04.cs
+test-pattern-05.cs
+test-pattern-07.cs
diff --git a/mcs/tests/test-tuple-01.cs b/mcs/tests/test-tuple-01.cs
new file mode 100644 (file)
index 0000000..bbea777
--- /dev/null
@@ -0,0 +1,53 @@
+using System;
+
+static class X
+{
+       static (int, string) Test1 ()
+       {
+               return ValueTuple.Create (1, "2");
+       }
+
+       static void Test2 ((int Item1, int Item2) arg)
+       {
+       }
+
+       static void Test3 ((int a, string b) arg)
+       {
+       }
+
+       static (int a, string b) Test4 ()
+       {
+               return ValueTuple.Create (1, "x");
+       }
+
+       static int Main ()
+       {
+               var res = Test1 ();
+               if (res.Item1 != 1) {
+                       return 1;
+               }
+
+               if (res.Item2 != "2") {
+                       return 2;
+               }
+
+               ValueTuple<int, string> res2 = res;
+
+               Test3 (ValueTuple.Create (1, "2"));
+
+               var res3 = Test4 ();
+               if (res3.Item1 != 1)
+                       return 3;
+
+               if (res3.a != 1)
+                       return 4;
+
+               if (res3.Item2 != "x")
+                       return 5;
+
+               if (res3.b != "x")
+                       return 6;
+
+               return 0;
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-tuple-02.cs b/mcs/tests/test-tuple-02.cs
new file mode 100644 (file)
index 0000000..c049275
--- /dev/null
@@ -0,0 +1,38 @@
+using System;
+
+class TupleConversions
+{
+       public static void Main ()
+       {
+               object oarg = 4;
+               (sbyte v1, long v2) t1 = (-1, 2);
+               var t2 = (-1, 2);
+
+               IComparable o = (x1: "a", x2: 1.ToString ());
+
+               var arg = (x1: 1, x2: 1.ToString ());
+               if (arg.x2 != "1")
+                       return;
+
+               Foo ((x1: (oarg, 'v'), x2: 1.ToString ()));
+
+               Test3 (ValueTuple.Create (1, "2"));
+
+               (int v1, string v2) y = (1, null);
+
+               (int v1, Action v2) y2 = (1, Main);
+               (int v1, Action v2) y3 = (ValueTuple<int, Action>) (1, Main);
+
+               (string v1, object v2) b = ("a", "b");
+
+               (int v1, long v2)? x = null;
+       }
+
+       static void Foo<T> (T arg)
+       {               
+       }
+
+       static void Test3 ((long a, object b) arg)
+       {
+       }
+}
diff --git a/mcs/tests/test-tuple-03.cs b/mcs/tests/test-tuple-03.cs
new file mode 100644 (file)
index 0000000..7eb45a8
--- /dev/null
@@ -0,0 +1,62 @@
+using System;
+using System.Linq.Expressions;
+
+class TupleDeconstruct
+{
+       public static int Main ()
+       {
+//             var (xx, yy) = (1, 2);
+//             if (xx != 1)
+//                     return 1;
+
+//             if (yy != 2)
+//                     return 2;
+
+               int x, y;
+               (x, y) = (1, 2);
+               if (x != 1)
+                       return 1;
+
+               if (y != 2)
+                       return 2;
+
+//             var (l1, l2) = ('a', 'b');
+
+//             var cwd = new ClassWithDeconstruct ();
+//             var (m1, m2) = cwd;
+
+//             (string, string) ss = cwd; // Error
+
+               return 0;
+       }
+
+       static void Test2 ()
+       {
+               var c = new C ();
+               (c.Prop1, c.Prop2) = (1, 2);
+       }
+
+       static void var1 (object o1, object o2)
+       {
+       }
+
+       static void TestCustom ()
+       {
+               return;
+       }
+}
+
+class ClassWithDeconstruct
+{
+       public void Deconstruct (out string f, out string s)
+       {
+               f = "a";
+               s = "z";
+       }
+}
+
+class C
+{
+       public int Prop1 { get; set; }
+       public int Prop2 { get; set; }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-tuple-04-lib.cs b/mcs/tests/test-tuple-04-lib.cs
new file mode 100644 (file)
index 0000000..469de9c
--- /dev/null
@@ -0,0 +1,14 @@
+// Compiler options: -t:library
+
+using System;
+using System.Collections.Generic;
+
+public class X
+{
+       public static (int a, string, bool b, object) Test1 ()
+       {
+               return ValueTuple.Create (1, "2", true, new X ());
+       }
+
+       public static (int x, (int x2, string y2), bool z) Field;
+}
diff --git a/mcs/tests/test-tuple-04.cs b/mcs/tests/test-tuple-04.cs
new file mode 100644 (file)
index 0000000..0b5b6ae
--- /dev/null
@@ -0,0 +1,17 @@
+// Compiler options: -r:test-tuple-04-lib.dll
+
+class Test
+{
+       public static int Main ()
+       {
+               var x = X.Test1 ();
+               if (x.b != true)
+                       return 1;
+
+               var z = X.Field;
+               if (z.z != false)
+                       return 2;
+
+               return 0;
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-tuple-05.cs b/mcs/tests/test-tuple-05.cs
new file mode 100644 (file)
index 0000000..593885d
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// tuple names attribute decoration
+//
+
+using System;
+using System.Collections;
+using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+using System.Linq;
+
+interface I<T>
+{
+}
+
+class B<T>
+{
+}
+
+class C // : B<(int a, int b)> // TODO: I<(a, b)
+{
+    public C((int a, int b) d)
+    {
+    }
+
+    public (int a, int b) a;
+    public (int, (int a, int b)) c;
+
+    public (int a, int b) Prop { set; get; }
+    public (int a, int b) Prop2 { set { } }
+
+    public (int a, int b)? this[(int a, int b) d] { set { } get { return null; } }
+
+    public (int a, int b)? Method(ref (int a, int b) d)
+    {
+        return null;
+    }
+
+    public (int a, int b)[] t;
+    public (int a, int b)[,] t2;
+    // TODO:    public Func<(int a, int b), int, (int c, int d)[]> v;
+    //    public I<(int a, int b)>[] iface;
+    // TODO:    public Action<(long, (long u, long))[], object, (int a, int b)> d2;
+    public (((int aa1, int aa2) a1, (int, int) a2) x1, ((int cc1, int cc2) b1, (int dd1, int dd2) b2) x2) d3;
+}
+
+delegate (int a, int b) Del((int a, int b) d);
+
+class Test
+{
+    public static int Main()
+    {
+        Type t = typeof(C);
+        Type ca = typeof(TupleElementNamesAttribute);
+        TupleElementNamesAttribute da;
+
+        if (t.GetMember("a")[0].GetCustomAttributes(ca, false).Length != 1)
+            return 1;
+
+        if (t.GetMember("c")[0].GetCustomAttributes(ca, false).Length != 1)
+            return 3;
+
+        if (t.GetMember("Prop")[0].GetCustomAttributes(ca, false).Length != 1)
+            return 4;
+
+        if (t.GetMember("get_Prop")[0].GetCustomAttributes(ca, false).Length != 0)
+            return 5;
+
+        if (t.GetMethod("get_Prop").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+            return 6;
+
+        if (t.GetMember("set_Prop")[0].GetCustomAttributes(ca, false).Length != 0)
+            return 7;
+
+        if (t.GetMethod("set_Prop").ReturnParameter.GetCustomAttributes(ca, false).Length != 0)
+            return 8;
+
+        if (t.GetMethod("set_Prop").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+            return 9;
+
+        if (t.GetMember("Prop2")[0].GetCustomAttributes(ca, false).Length != 1)
+            return 10;
+
+        if (t.GetMember("set_Prop2")[0].GetCustomAttributes(ca, false).Length != 0)
+            return 11;
+
+        if (t.GetMember("Item")[0].GetCustomAttributes(ca, false).Length != 1)
+            return 12;
+
+        if (t.GetMethod("get_Item").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+            return 13;
+
+        if (t.GetMethod("get_Item").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+            return 14;
+
+        if (t.GetMethod("set_Item").ReturnParameter.GetCustomAttributes(ca, false).Length != 0)
+            return 15;
+
+        if (t.GetMethod("set_Item").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+            return 16;
+
+        if (t.GetMethod("set_Item").GetParameters()[1].GetCustomAttributes(ca, false).Length != 1)
+            return 17;
+
+        if (t.GetMember("Method")[0].GetCustomAttributes(ca, false).Length != 0)
+            return 18;
+
+        var res = t.GetMethod("Method").GetParameters()[0].GetCustomAttributes(ca, false);
+        if (res.Length != 1)
+            return 19;
+
+        da = res[0] as TupleElementNamesAttribute;
+        if (da == null)
+            return 190;
+        if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+            return 191;
+
+        if (t.GetConstructors()[0].GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+            return 20;
+
+        if (t.GetConstructors()[0].GetCustomAttributes(ca, false).Length != 0)
+            return 21;
+
+        //        if (t.GetCustomAttributes(ca, false).Length != 1)
+        //            return 22;
+
+        // Transformations
+        da = t.GetMember("t")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+        if (da == null)
+            return 40;
+
+        if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+            return 41;
+
+        da = t.GetMember("t2")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+        if (da == null)
+            return 42;
+
+        if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+            return 43;
+
+        //da = t.GetMember("v")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+        //if (da == null)
+        //    return 44;
+
+        //if (!da.TransformNames.SequenceEqual(new string[] { "a", "b", "c", "d" }))
+        //    return 45;
+
+        //da = t.GetMember("iface")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+        //if (da == null)
+        //    return 46;
+
+        //if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+        //    return 47;
+
+        //da = t.GetMember("d2")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+        //if (da == null)
+        //    return 48;
+        //if (!da.TransformNames.SequenceEqual(new string[] { null, null, "u", null, "a", "b" }))
+        //    return 49;
+
+        da = t.GetMember("d3")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+        if (da == null)
+            return 50;
+        if (!da.TransformNames.SequenceEqual(new string[] { "x1", "x2", "a1", "a2", "aa1", "aa2", null, null, "b1", "b2", "cc1", "cc2", "dd1", "dd2" }))
+            return 51;
+
+        t = typeof(Del);
+
+        if (t.GetMember("Invoke")[0].GetCustomAttributes(ca, false).Length != 0)
+            return 100;
+
+        if (t.GetMethod("Invoke").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+            return 101;
+
+        if (t.GetMethod("Invoke").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+            return 102;
+
+        Console.WriteLine("ok");
+        return 0;
+    }
+}
index 460fe02f0e126c5c93eb077380f6403f8ba1b625..77879db1c1e3bf2634c5118ca8556b6350456991 100644 (file)
@@ -35,7 +35,7 @@
     </type>
     <type name="Test">
       <method name="Int32 Main()" attrs="150">
-        <size>1292</size>
+        <size>1316</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
         <size>0</size>
       </method>
     </type>
+    <type name="B`1[T]">
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
   </test>
   <test name="dtest-002.cs">
     <type name="C">
       </method>
     </type>
   </test>
-  <test name="test-pattern-04.cs">
-    <type name="RecursivePattern">
-      <method name="Int32 Main()" attrs="145">
-        <size>750</size>
-      </method>
-      <method name="Void .ctor()" attrs="6278">
-        <size>7</size>
-      </method>
-    </type>
-    <type name="C1">
-      <method name="Boolean op_Is(C1, Int32 ByRef)" attrs="2198">
-        <size>13</size>
-      </method>
-      <method name="Boolean op_Is(C1, C1 ByRef, C1 ByRef)" attrs="2198">
-        <size>16</size>
-      </method>
-      <method name="Void .ctor()" attrs="6278">
-        <size>7</size>
-      </method>
-    </type>
-    <type name="S">
-      <method name="Boolean op_Is(S, System.Nullable`1[System.Int32] ByRef, System.Decimal ByRef)" attrs="2198">
-        <size>34</size>
-      </method>
-    </type>
-  </test>
-  <test name="test-pattern-05.cs">
-    <type name="RecursiveNamedPattern">
-      <method name="Int32 Main()" attrs="150">
-        <size>204</size>
-      </method>
-      <method name="Void .ctor()" attrs="6278">
-        <size>7</size>
-      </method>
-    </type>
-    <type name="C">
-      <method name="Boolean op_Is(C, Int64 ByRef, System.String ByRef)" attrs="2198">
-        <size>22</size>
-      </method>
-      <method name="Boolean op_Is(C)" attrs="2198">
-        <size>10</size>
-      </method>
-      <method name="Void .ctor()" attrs="6278">
-        <size>7</size>
-      </method>
-    </type>
-  </test>
   <test name="test-pattern-06.cs">
     <type name="RecursiveNamedPattern">
       <method name="Int32 Main()" attrs="150">
       </method>
     </type>
   </test>
-  <test name="test-pattern-07.cs">
-    <type name="PropertyPattern">
-      <method name="Int32 Main()" attrs="145">
-        <size>684</size>
-      </method>
-      <method name="Void .ctor()" attrs="6278">
-        <size>7</size>
-      </method>
-    </type>
-    <type name="X">
-      <method name="System.Object get_Field()" attrs="2182">
-        <size>14</size>
-      </method>
-      <method name="Void set_Field(System.Object)" attrs="2182">
-        <size>8</size>
-      </method>
-      <method name="Void .ctor()" attrs="6278">
-        <size>7</size>
-      </method>
-    </type>
-    <type name="Y">
-      <method name="Char get_Prop()" attrs="2182">
-        <size>14</size>
-      </method>
-      <method name="Void set_Prop(Char)" attrs="2182">
-        <size>8</size>
-      </method>
-      <method name="Boolean op_Is(Y, Int32 ByRef)" attrs="2198">
-        <size>13</size>
-      </method>
-      <method name="Void .ctor()" attrs="6278">
-        <size>7</size>
-      </method>
-    </type>
-    <type name="X">
-      <method name="System.Object get_Value()" attrs="2182">
-        <size>14</size>
-      </method>
-      <method name="Void set_Value(System.Object)" attrs="2182">
-        <size>8</size>
-      </method>
-    </type>
-    <type name="&lt;PatternMatchingHelper&gt;">
-      <method name="Boolean NumberMatcher(System.Object, System.Object, Boolean)" attrs="150">
-        <size>69</size>
-      </method>
-    </type>
-    <type name="X">
-      <method name="System.Nullable`1[System.Int64] get_NullableValue()" attrs="2182">
-        <size>14</size>
-      </method>
-      <method name="Void set_NullableValue(System.Nullable`1[System.Int64])" attrs="2182">
-        <size>8</size>
-      </method>
-    </type>
-  </test>
   <test name="test-pragma-unrecognized.cs">
     <type name="C">
       <method name="Void Main()" attrs="150">
       </method>
     </type>
   </test>
+  <test name="test-tuple-01.cs">
+    <type name="X">
+      <method name="System.ValueTuple`2[System.Int32,System.String] Test1()" attrs="145">
+        <size>20</size>
+      </method>
+      <method name="Void Test2(System.ValueTuple`2[System.Int32,System.Int32])" attrs="145">
+        <size>2</size>
+      </method>
+      <method name="Void Test3(System.ValueTuple`2[System.Int32,System.String])" attrs="145">
+        <size>2</size>
+      </method>
+      <method name="System.ValueTuple`2[System.Int32,System.String] Test4()" attrs="145">
+        <size>40</size>
+      </method>
+      <method name="Int32 Main()" attrs="145">
+        <size>210</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-tuple-02.cs">
+    <type name="TupleConversions">
+      <method name="Void Main()" attrs="150">
+        <size>314</size>
+      </method>
+      <method name="Void Foo[T](T)" attrs="145">
+        <size>2</size>
+      </method>
+      <method name="Void Test3(System.ValueTuple`2[System.Int64,System.Object])" attrs="145">
+        <size>2</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-tuple-03.cs">
+    <type name="TupleDeconstruct">
+      <method name="Int32 Main()" attrs="150">
+        <size>42</size>
+      </method>
+      <method name="Void Test2()" attrs="145">
+        <size>22</size>
+      </method>
+      <method name="Void var1(System.Object, System.Object)" attrs="145">
+        <size>2</size>
+      </method>
+      <method name="Void TestCustom()" attrs="145">
+        <size>7</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="ClassWithDeconstruct">
+      <method name="Void Deconstruct(System.String ByRef, System.String ByRef)" attrs="134">
+        <size>16</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C">
+      <method name="Int32 get_Prop1()" attrs="2182">
+        <size>14</size>
+      </method>
+      <method name="Void set_Prop1(Int32)" attrs="2182">
+        <size>8</size>
+      </method>
+      <method name="Int32 get_Prop2()" attrs="2182">
+        <size>14</size>
+      </method>
+      <method name="Void set_Prop2(Int32)" attrs="2182">
+        <size>8</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-tuple-04.cs">
+    <type name="Test">
+      <method name="Int32 Main()" attrs="150">
+        <size>60</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-tuple-05.cs">
+    <type name="B`1[T]">
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C">
+      <method name="Void set_Prop(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+        <size>28</size>
+      </method>
+      <method name="System.ValueTuple`2[System.Int32,System.Int32] get_Prop()" attrs="2182">
+        <size>34</size>
+      </method>
+      <method name="Void set_Prop2(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+        <size>2</size>
+      </method>
+      <method name="Void set_Item(System.ValueTuple`2[System.Int32,System.Int32], System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]])" attrs="2182">
+        <size>2</size>
+      </method>
+      <method name="System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]] get_Item(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+        <size>18</size>
+      </method>
+      <method name="System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]] Method(System.ValueTuple`2[System.Int32,System.Int32] ByRef)" attrs="134">
+        <size>18</size>
+      </method>
+      <method name="Void .ctor(ValueTuple`2)" attrs="6278">
+        <size>8</size>
+      </method>
+    </type>
+    <type name="Del">
+      <method name="System.ValueTuple`2[System.Int32,System.Int32] Invoke(System.ValueTuple`2[System.Int32,System.Int32])" attrs="454">
+        <size>0</size>
+      </method>
+      <method name="System.IAsyncResult BeginInvoke(System.ValueTuple`2[System.Int32,System.Int32], System.AsyncCallback, System.Object)" attrs="454">
+        <size>0</size>
+      </method>
+      <method name="System.ValueTuple`2[System.Int32,System.Int32] EndInvoke(System.IAsyncResult)" attrs="454">
+        <size>0</size>
+      </method>
+      <method name="Void .ctor(Object, IntPtr)" attrs="6278">
+        <size>0</size>
+      </method>
+    </type>
+    <type name="Test">
+      <method name="Int32 Main()" attrs="150">
+        <size>1338</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-var-01.cs">
     <type name="Test">
       <method name="Int32 Main()" attrs="150">