Includes the following commits: 6f5bfe5cf5a 3812d1c13fc a80f3d0d87c b2f051f0b19 2a202a8478b 4d7d1606d73 d9970305731 94e80fc8d7f 0b9280083a9 07d1e5f36a5 5f279f14aa2 889421f3bef f4c0fd3dc11 71df5c63b46 d6e5bf16782 207f5c2cd6d c512752a416 9aca8d5fe4b diff --git a/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs b/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs index 97f9e047e6d..f8bf63455de 100644 --- a/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs +++ b/mcs/class/Mono.CSharp/Test/Evaluator/TypesTest.cs @@ -131,5 +131,17 @@ namespace MonoTests.EvaluatorTest { Evaluator.Run ("public class TestClass { private TestEnum _te; public string Get() { return _te.ToString(); } } public enum TestEnum { First, Second }"); } + + [Test] + public void EnumTypeWithOrderDependency () + { + Evaluator.Run ("public class TestClass { public enum TestEnum { Val1, Val2, Val3 } public TestEnum test; public TestClass() { test = TestEnum.Val3; } }"); + object res = Evaluator.Evaluate ("new TestClass()"); + + var fields = res.GetType ().GetFields (); + foreach (var field in fields) { + Console.WriteLine ($"{field.Name} = {field.MemberType}"); + } + } } } \ No newline at end of file diff --git a/mcs/errors/cs0023-30.cs b/mcs/errors/cs0023-30.cs new file mode 100644 index 00000000000..fc19cc24e3e --- /dev/null +++ b/mcs/errors/cs0023-30.cs @@ -0,0 +1,11 @@ +// CS0023: The `is' operator cannot be applied to operand of type `default' +// Line: 9 +// Compiler options: -langversion:latest + +class C +{ + static void Main () + { + bool d = default is C; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0029-39.cs b/mcs/errors/cs0029-39.cs new file mode 100644 index 00000000000..0ed200036dc --- /dev/null +++ b/mcs/errors/cs0029-39.cs @@ -0,0 +1,15 @@ +// CS0029: Cannot implicitly convert type `S' to `object' +// Line: 13 +// Compiler options: -langversion:latest + +public ref struct S +{ +} + +class Test +{ + public static void Main () + { + object o = new S (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs0029-40.cs b/mcs/errors/cs0029-40.cs new file mode 100644 index 00000000000..6d9167c31fa --- /dev/null +++ b/mcs/errors/cs0029-40.cs @@ -0,0 +1,19 @@ +// CS0029: Cannot implicitly convert type `S' to `System.ValueType' +// Line: 16 +// Compiler options: -langversion:latest + +using System; + +public ref struct S +{ +} + +class Test +{ + public static void Main () + { + var s = default (S); + ValueType s2 = s; + var res = default (S).ToString (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs0029-41.cs b/mcs/errors/cs0029-41.cs new file mode 100644 index 00000000000..1a65f52f737 --- /dev/null +++ b/mcs/errors/cs0029-41.cs @@ -0,0 +1,12 @@ +// CS0029: Cannot implicitly convert type `System.TypedReference' to `object' +// Line: 10 + +using System; + +class Test +{ + public static void Main () + { + var res = default (TypedReference).ToString (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs0029-42.cs b/mcs/errors/cs0029-42.cs new file mode 100644 index 00000000000..c7671000c76 --- /dev/null +++ b/mcs/errors/cs0029-42.cs @@ -0,0 +1,10 @@ +// CS0029: Cannot implicitly convert type `string' to `int' +// Line: 8 + +class C +{ + void Exists (int _) + { + _ = "2"; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0030-17.cs b/mcs/errors/cs0030-17.cs new file mode 100644 index 00000000000..b72b8bf71e5 --- /dev/null +++ b/mcs/errors/cs0030-17.cs @@ -0,0 +1,15 @@ +// CS0030: Cannot convert type `object' to `S' +// Line: 13 +// Compiler options: -langversion:latest + +ref struct S +{ +} + +class X +{ + public static void Foo (object o) + { + var res = (S) o; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0103-18.cs b/mcs/errors/cs0103-18.cs new file mode 100644 index 00000000000..8cec755d23d --- /dev/null +++ b/mcs/errors/cs0103-18.cs @@ -0,0 +1,10 @@ +// CS0103: The name `_' does not exist in the current context +// Line: 8 + +class C +{ + void Test () + { + _.ToString (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs0123-10.cs b/mcs/errors/cs0123-10.cs new file mode 100644 index 00000000000..43d5e5d6368 --- /dev/null +++ b/mcs/errors/cs0123-10.cs @@ -0,0 +1,18 @@ +// CS0123: A method or delegate `object.ToString()' parameters do not match delegate `System.Func()' parameters +// Line: 16 +// Compiler options: -langversion:latest + +using System; + +public ref struct S +{ +} + +class Test +{ + public static void Main () + { + var s = new S (); + Func f = s.ToString; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0123-11.cs b/mcs/errors/cs0123-11.cs new file mode 100644 index 00000000000..427b628c159 --- /dev/null +++ b/mcs/errors/cs0123-11.cs @@ -0,0 +1,12 @@ +// CS0123: A method or delegate `object.ToString()' parameters do not match delegate `System.Func()' parameters +// Line: 16 + +using System; + +class Test +{ + public static void Main () + { + Func f = default (TypedReference).ToString; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0133-2.cs b/mcs/errors/cs0133-2.cs index b7a37182d73..48488876f7e 100644 --- a/mcs/errors/cs0133-2.cs +++ b/mcs/errors/cs0133-2.cs @@ -1,4 +1,4 @@ -// CS0133: The expression being assigned to `c' must be constant +// CS0133: The expression being assigned to `c' must be a constant or default value // Line: 10 class C diff --git a/mcs/errors/cs0133-3.cs b/mcs/errors/cs0133-3.cs index caae3bde68c..2f7dac6880d 100644 --- a/mcs/errors/cs0133-3.cs +++ b/mcs/errors/cs0133-3.cs @@ -1,5 +1,5 @@ -// CS0133: The expression being assigned to `Foo' must be constant -// Line: 12 +// CS0133: The expression being assigned to `Foo' must be a constant or default value +// Line: 8 class T { diff --git a/mcs/errors/cs0133-4.cs b/mcs/errors/cs0133-4.cs index 41fe639b446..54162d544ca 100644 --- a/mcs/errors/cs0133-4.cs +++ b/mcs/errors/cs0133-4.cs @@ -1,4 +1,4 @@ -// CS0133: The expression being assigned to `S.pathName' must be constant +// CS0133: The expression being assigned to `S.pathName' must be a constant or default value // Line: 12 // Compiler options: -unsafe diff --git a/mcs/errors/cs0133-5.cs b/mcs/errors/cs0133-5.cs index a49f265c690..32e6bfdf416 100644 --- a/mcs/errors/cs0133-5.cs +++ b/mcs/errors/cs0133-5.cs @@ -1,4 +1,4 @@ -// CS0133: The expression being assigned to `b' must be constant +// CS0133: The expression being assigned to `b' must be a constant or default value // Line: 8 class X diff --git a/mcs/errors/cs0133-6.cs b/mcs/errors/cs0133-6.cs index a523169cdbd..28448dd6de8 100644 --- a/mcs/errors/cs0133-6.cs +++ b/mcs/errors/cs0133-6.cs @@ -1,4 +1,4 @@ -// CS0133: The expression being assigned to `o' must be constant +// CS0133: The expression being assigned to `o' must be a constant or default value // Line: 8 class X diff --git a/mcs/errors/cs0133-7.cs b/mcs/errors/cs0133-7.cs index 10d82d9fe5e..024bc148229 100644 --- a/mcs/errors/cs0133-7.cs +++ b/mcs/errors/cs0133-7.cs @@ -1,4 +1,4 @@ -// CS0133: The expression being assigned to `o' must be constant +// CS0133: The expression being assigned to `o' must be a constant or default value // Line: 8 class X diff --git a/mcs/errors/cs0133.cs b/mcs/errors/cs0133.cs index 094194deabb..f0dda9ee3cb 100644 --- a/mcs/errors/cs0133.cs +++ b/mcs/errors/cs0133.cs @@ -1,5 +1,6 @@ -// CS0133: The expression being assigned to `x' must be constant -// Line: 6 +// CS0133: The expression being assigned to `x' must be a constant or default value +// Line: 7 + class X { X (int arg) { diff --git a/mcs/errors/cs0306-4.cs b/mcs/errors/cs0306-4.cs new file mode 100644 index 00000000000..4653512e55b --- /dev/null +++ b/mcs/errors/cs0306-4.cs @@ -0,0 +1,15 @@ +// CS0306: The type `S' may not be used as a type argument +// Line: 13 +// Compiler options: -langversion:latest + +public ref struct S +{ +} + +class Test +{ + public static void Foo () + { + Test local; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0611-3.cs b/mcs/errors/cs0611-3.cs new file mode 100644 index 00000000000..6eda773dd24 --- /dev/null +++ b/mcs/errors/cs0611-3.cs @@ -0,0 +1,15 @@ +// CS0611: Array elements cannot be of type `S' +// Line: 13 +// Compiler options: -langversion:latest + +public ref struct S +{ +} + +class Test +{ + public static void Main () + { + var x = new S[0]; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0815-9.cs b/mcs/errors/cs0815-9.cs new file mode 100644 index 00000000000..f54703349be --- /dev/null +++ b/mcs/errors/cs0815-9.cs @@ -0,0 +1,11 @@ +// CS0815: An implicitly typed local variable declaration cannot be initialized with `default' +// Line: 9 +// Compiler options: -langversion:latest + +static class X +{ + public static void Main () + { + var x = default; + } +} \ No newline at end of file diff --git a/mcs/errors/cs1502-11.cs b/mcs/errors/cs1502-11.cs deleted file mode 100644 index 82dcb3a2c17..00000000000 --- a/mcs/errors/cs1502-11.cs +++ /dev/null @@ -1,11 +0,0 @@ -// CS1502: The best overloaded method match for `string.String(char*)' has some invalid arguments -// Line: 8 - -class C -{ - static string Prop { - get { - return new string ("s"); - } - } -} diff --git a/mcs/errors/cs1599-2.cs b/mcs/errors/cs1599-2.cs index 941ff6bb0d6..28aa05b2ed3 100644 --- a/mcs/errors/cs1599-2.cs +++ b/mcs/errors/cs1599-2.cs @@ -1,4 +1,4 @@ -// CS1599: Method or delegate cannot return type `System.ArgIterator' +// CS1599: The return type of `System.ArgIterator' is not allowed // Line: 8 using System; diff --git a/mcs/errors/cs1599-3.cs b/mcs/errors/cs1599-3.cs index e4869dcaf70..9d378099d82 100644 --- a/mcs/errors/cs1599-3.cs +++ b/mcs/errors/cs1599-3.cs @@ -1,4 +1,4 @@ -// CS1599: Method or delegate cannot return type `System.ArgIterator' +// CS1599: The return type of `System.ArgIterator' is not allowed // Line: 8 using System; diff --git a/mcs/errors/cs1599-4.cs b/mcs/errors/cs1599-4.cs new file mode 100644 index 00000000000..358eee59a13 --- /dev/null +++ b/mcs/errors/cs1599-4.cs @@ -0,0 +1,12 @@ +// CS1599: The return type of `System.TypedReference' is not allowed +// Line: 8 + +using System; + +public class Program +{ + public static TypedReference operator + (int a, Program b) + { + throw new ApplicationException (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs1599.cs b/mcs/errors/cs1599.cs index 5cef32d7f97..871d9fb3e7a 100644 --- a/mcs/errors/cs1599.cs +++ b/mcs/errors/cs1599.cs @@ -1,4 +1,4 @@ -// CS1599: Method or delegate cannot return type `System.TypedReference' +// CS1599: The return type of `System.TypedReference' is not allowed // Line: 8 using System; diff --git a/mcs/errors/cs1644-57.cs b/mcs/errors/cs1644-57.cs new file mode 100644 index 00000000000..7ee98373080 --- /dev/null +++ b/mcs/errors/cs1644-57.cs @@ -0,0 +1,7 @@ +// CS1644: Feature `ref structs' cannot be used because it is not part of the C# 7.0 language specification +// Line: 5 +// Compiler options: -langversion:7 + +ref struct S +{ +} \ No newline at end of file diff --git a/mcs/errors/cs1644-58.cs b/mcs/errors/cs1644-58.cs new file mode 100644 index 00000000000..e994cf338bd --- /dev/null +++ b/mcs/errors/cs1644-58.cs @@ -0,0 +1,8 @@ +// CS1644: Feature `default literal' cannot be used because it is not part of the C# 7.0 language specification +// Line: 7 +// Compiler options: -langversion:7 + +class X +{ + int i = default; +} diff --git a/mcs/errors/cs1644-59.cs b/mcs/errors/cs1644-59.cs new file mode 100644 index 00000000000..2f8aed6b958 --- /dev/null +++ b/mcs/errors/cs1644-59.cs @@ -0,0 +1,13 @@ +// CS1644: Feature `readonly references' cannot be used because it is not part of the C# 7.0 language specification +// Line: 9 +// Compiler options: -langversion:7 + +class X +{ + int i; + + ref readonly int Test () + { + return ref i; + } +} diff --git a/mcs/errors/cs1644-60.cs b/mcs/errors/cs1644-60.cs new file mode 100644 index 00000000000..ca9547bc561 --- /dev/null +++ b/mcs/errors/cs1644-60.cs @@ -0,0 +1,11 @@ +// CS1644: Feature `discards' cannot be used because it is not part of the C# 6.0 language specification +// Line: 9 +// Compiler options: -langversion:6 + +class X +{ + int Test () + { + _ = 2; + } +} diff --git a/mcs/errors/cs1738-2.cs b/mcs/errors/cs1738-2.cs index f59221f4c7a..44b3f6d1b14 100644 --- a/mcs/errors/cs1738-2.cs +++ b/mcs/errors/cs1738-2.cs @@ -1,4 +1,4 @@ -// CS1738: Named arguments must appear after the positional arguments +// CS1738: Named arguments must appear after the positional arguments when using language version older than 7.2 // Line: 13 using System; diff --git a/mcs/errors/cs1738-3.cs b/mcs/errors/cs1738-3.cs index 53c4efc3553..901ac0e5d59 100644 --- a/mcs/errors/cs1738-3.cs +++ b/mcs/errors/cs1738-3.cs @@ -1,4 +1,4 @@ -// CS1738: Named arguments must appear after the positional arguments +// CS1738: Named arguments must appear after the positional arguments when using language version older than 7.2 // Line: 14 class C diff --git a/mcs/errors/cs1738.cs b/mcs/errors/cs1738.cs index dab9a61160b..537bc17b917 100644 --- a/mcs/errors/cs1738.cs +++ b/mcs/errors/cs1738.cs @@ -1,4 +1,4 @@ -// CS1738: Named arguments must appear after the positional arguments +// CS1738: Named arguments must appear after the positional arguments when using language version older than 7.2 // Line: 12 class C diff --git a/mcs/errors/cs1983.cs b/mcs/errors/cs1983.cs index a2ef6c150d6..76d2db4e677 100644 --- a/mcs/errors/cs1983.cs +++ b/mcs/errors/cs1983.cs @@ -1,4 +1,4 @@ -// CS1983: The return type of an async method must be void, Task, or Task +// CS1983: The return type of an async method must be void or task type // Line: 6 class C diff --git a/mcs/errors/cs4012-3.cs b/mcs/errors/cs4012-3.cs new file mode 100644 index 00000000000..fb3d1dc276f --- /dev/null +++ b/mcs/errors/cs4012-3.cs @@ -0,0 +1,19 @@ +// CS4012: Parameters or local variables of type `S' cannot be declared in async methods or iterators +// Line: 16 +// Compiler options: -langversion:latest + +using System; +using System.Threading.Tasks; + +public ref struct S +{ +} + +class C +{ + public async void Test () + { + var tr = new S (); + await Task.Factory.StartNew (() => 6); + } +} \ No newline at end of file diff --git a/mcs/errors/cs8175-2.cs b/mcs/errors/cs8175-2.cs new file mode 100644 index 00000000000..27c4babf8bf --- /dev/null +++ b/mcs/errors/cs8175-2.cs @@ -0,0 +1,19 @@ +// CS8175: Cannot use by-reference variable `s' inside an anonymous method, lambda expression, or query expression +// Line: 17 +// Compiler options: -langversion:latest + +using System; + +public ref struct S +{ +} + +class Test +{ + public static void Main () + { + var s = new S (); + + Action a = () => Console.WriteLine (s); + } +} \ No newline at end of file diff --git a/mcs/errors/cs8183.cs b/mcs/errors/cs8183.cs new file mode 100644 index 00000000000..f9e9004b737 --- /dev/null +++ b/mcs/errors/cs8183.cs @@ -0,0 +1,11 @@ +// CS8183: Cannot infer the type of implicitly-typed discard +// Line: 9 +// Compiler options: -langversion:7.2 + +class X +{ + public static void Main () + { + _ = default; + } +} \ No newline at end of file diff --git a/mcs/errors/cs8184.cs b/mcs/errors/cs8184.cs new file mode 100644 index 00000000000..19a4685d7bd --- /dev/null +++ b/mcs/errors/cs8184.cs @@ -0,0 +1,10 @@ +// CS8184: A deconstruction cannot mix declarations and expressions on the left-hand-side +// Line: 8 + +class X +{ + public static void Main () + { + (int a, b) = (1, 2); + } +} \ No newline at end of file diff --git a/mcs/errors/cs8207.cs b/mcs/errors/cs8207.cs new file mode 100644 index 00000000000..31090948b45 --- /dev/null +++ b/mcs/errors/cs8207.cs @@ -0,0 +1,19 @@ +// CS8207: An expression tree cannot contain a discard +// Line: 11 + +using System; +using System.Linq.Expressions; + +class X +{ + void Test () + { + Expression> e = () => TryGetValue (out _); + } + + bool TryGetValue (out int arg) + { + arg = 3; + return true; + } +} diff --git a/mcs/errors/cs8209.cs b/mcs/errors/cs8209.cs new file mode 100644 index 00000000000..3a46a206c8e --- /dev/null +++ b/mcs/errors/cs8209.cs @@ -0,0 +1,10 @@ +// CS8209: Cannot assign void to a discard +// Line: 8 + +class C +{ + public static void Main () + { + _ = Main (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs8310.cs b/mcs/errors/cs8310.cs new file mode 100644 index 00000000000..134624c03b7 --- /dev/null +++ b/mcs/errors/cs8310.cs @@ -0,0 +1,11 @@ +// CS8310: Operator `+' cannot be applied to operand `default' +// Line: 9 +// Compiler options: -langversion:latest + +class C +{ + static void Main () + { + int h = 1 + default; + } +} \ No newline at end of file diff --git a/mcs/errors/cs8311.cs b/mcs/errors/cs8311.cs new file mode 100644 index 00000000000..5b35229442d --- /dev/null +++ b/mcs/errors/cs8311.cs @@ -0,0 +1,12 @@ +// CS8311: Cannot use a default literal as an argument to a dynamically dispatched operation +// Line: 10 +// Compiler options: -langversion:latest + +class C +{ + static void Main () + { + dynamic d = null; + d.M2 (default); + } +} \ No newline at end of file diff --git a/mcs/errors/cs8312.cs b/mcs/errors/cs8312.cs new file mode 100644 index 00000000000..d2ad3f52f02 --- /dev/null +++ b/mcs/errors/cs8312.cs @@ -0,0 +1,12 @@ +// CS8312: Use of default literal is not valid in this context +// Line: 9 +// Compiler options: -langversion:latest + +class C +{ + static void Main () + { + foreach (var x in default) { + } + } +} \ No newline at end of file diff --git a/mcs/errors/cs8315.cs b/mcs/errors/cs8315.cs new file mode 100644 index 00000000000..c40bf8613b4 --- /dev/null +++ b/mcs/errors/cs8315.cs @@ -0,0 +1,11 @@ +// CS8315: Operator `==' is ambiguous on operands `default' and `default' +// Line: 9 +// Compiler options: -langversion:latest + +class C +{ + static void Main () + { + bool d = default == default; + } +} \ No newline at end of file diff --git a/mcs/errors/cs8323.cs b/mcs/errors/cs8323.cs new file mode 100644 index 00000000000..c6c9309ec0d --- /dev/null +++ b/mcs/errors/cs8323.cs @@ -0,0 +1,15 @@ +// CS8323: Named argument `str' is used out of position but is followed by positional argument +// Line: 9 +// Compiler options: -langversion:7.2 + +class X +{ + public static void Main () + { + Test (str: "", ""); + } + + static void Test (int arg, string str) + { + } +} \ No newline at end of file diff --git a/mcs/errors/cs8324.cs b/mcs/errors/cs8324.cs new file mode 100644 index 00000000000..8a0be1aefb9 --- /dev/null +++ b/mcs/errors/cs8324.cs @@ -0,0 +1,12 @@ +// CS8324: Named argument specifications must appear after all fixed arguments have been specified in a dynamic invocation +// Line: 10 +// Compiler options: -langversion:7.2 + +class C +{ + void M () + { + dynamic d = new object (); + d.M (arg: 1, ""); + } +} \ No newline at end of file diff --git a/mcs/errors/cs8343.cs b/mcs/errors/cs8343.cs new file mode 100644 index 00000000000..b6aa8e83a09 --- /dev/null +++ b/mcs/errors/cs8343.cs @@ -0,0 +1,12 @@ +// CS8343: `S': ref structs cannot implement interfaces +// Line: 7 +// Compiler options: -langversion:latest + +using System; + +public ref struct S : IDisposable +{ + public void Dispose () + { + } +} diff --git a/mcs/errors/cs8345-2.cs b/mcs/errors/cs8345-2.cs new file mode 100644 index 00000000000..3f6137b1b56 --- /dev/null +++ b/mcs/errors/cs8345-2.cs @@ -0,0 +1,12 @@ +// CS8345: Field or auto-implemented property cannot be of type `S' unless it is an instance member of a ref struct +// Line: 11 +// Compiler options: -langversion:latest + +public ref struct S +{ +} + +ref struct Test +{ + static S field; +} \ No newline at end of file diff --git a/mcs/errors/cs8345.cs b/mcs/errors/cs8345.cs new file mode 100644 index 00000000000..0b5bd05518f --- /dev/null +++ b/mcs/errors/cs8345.cs @@ -0,0 +1,12 @@ +// CS8345: Field or auto-implemented property cannot be of type `S' unless it is an instance member of a ref struct +// Line: 11 +// Compiler options: -langversion:latest + +public ref struct S +{ +} + +struct Test +{ + S field; +} \ No newline at end of file diff --git a/mcs/errors/cs8346.cs b/mcs/errors/cs8346.cs new file mode 100644 index 00000000000..58e22a2ae7f --- /dev/null +++ b/mcs/errors/cs8346.cs @@ -0,0 +1,13 @@ +// CS8346: Cannot convert a stackalloc expression of type `byte' to type `System.Span' +// Line: 11 +// Compiler options: -langversion:7.2 + +using System; + +class X +{ + public static void Main () + { + Span stackSpan = stackalloc byte[1]; + } +} \ No newline at end of file diff --git a/mcs/mcs/argument.cs b/mcs/mcs/argument.cs index 8421b4dfbfc..5b1003dbadf 100644 --- a/mcs/mcs/argument.cs +++ b/mcs/mcs/argument.cs @@ -106,11 +106,6 @@ namespace Mono.CSharp public virtual Expression CreateExpressionTree (ResolveContext rc) { - if (Type.Kind == MemberKind.ByRef) { - rc.Report.Error (8153, Expr.Location, "An expression tree lambda cannot contain a call to a method, property, or indexer that returns by reference"); - return null; - } - if (ArgType == AType.Default) rc.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter"); diff --git a/mcs/mcs/assign.cs b/mcs/mcs/assign.cs index a07c8c0ef39..596623feae4 100644 --- a/mcs/mcs/assign.cs +++ b/mcs/mcs/assign.cs @@ -391,9 +391,21 @@ namespace Mono.CSharp { return System.Linq.Expressions.Expression.Assign (target_object, source_object); } - protected virtual Expression ResolveConversions (ResolveContext ec) + protected virtual Expression ResolveConversions (ResolveContext rc) { - source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location); + var ttype = target.Type; + var stackAlloc = source as StackAlloc; + if (stackAlloc != null && ttype.Arity == 1 && ttype.GetDefinition () == rc.Module.PredefinedTypes.SpanGeneric.TypeSpec && + rc.Module.Compiler.Settings.Version >= LanguageVersion.V_7_2) { + + var etype = ttype.TypeArguments [0]; + var stype = ((PointerContainer)source.Type).Element; + if (etype == stype && stackAlloc.ResolveSpanConversion (rc, ttype)) { + return this; + } + } + + source = Convert.ImplicitConversionRequired (rc, source, ttype, source.Location); if (source == null) return null; diff --git a/mcs/mcs/async.cs b/mcs/mcs/async.cs index fd6499346e8..643aed5e568 100644 --- a/mcs/mcs/async.cs +++ b/mcs/mcs/async.cs @@ -628,58 +628,112 @@ namespace Mono.CSharp protected override bool DoDefineMembers () { - PredefinedType builder_type; - PredefinedMember bf; - PredefinedMember bs; - PredefinedMember sr; - PredefinedMember se; - PredefinedMember sm; + TypeSpec bt; bool has_task_return_type = false; - var pred_members = Module.PredefinedMembers; + var istate_machine = Module.PredefinedTypes.IAsyncStateMachine; + MethodSpec set_statemachine; - if (return_type.Kind == MemberKind.Void) { - builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; - bf = pred_members.AsyncVoidMethodBuilderCreate; - bs = pred_members.AsyncVoidMethodBuilderStart; - sr = pred_members.AsyncVoidMethodBuilderSetResult; - se = pred_members.AsyncVoidMethodBuilderSetException; - sm = pred_members.AsyncVoidMethodBuilderSetStateMachine; - } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { - builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; - bf = pred_members.AsyncTaskMethodBuilderCreate; - bs = pred_members.AsyncTaskMethodBuilderStart; - sr = pred_members.AsyncTaskMethodBuilderSetResult; - se = pred_members.AsyncTaskMethodBuilderSetException; - sm = pred_members.AsyncTaskMethodBuilderSetStateMachine; - task = pred_members.AsyncTaskMethodBuilderTask.Get (); + if (return_type.IsCustomTaskType ()) { + // + // TODO: Would be nice to cache all this on per-type basis + // + var btypes = Compiler.BuiltinTypes; + bt = return_type.MemberDefinition.GetAsyncMethodBuilder (); + TypeSpec bt_inflated; + if (return_type.IsGeneric) { + bt_inflated = bt.MakeGenericType (Module, bt.MemberDefinition.TypeParameters); + } else { + bt_inflated = bt; + } + + var set_result_sign = MemberFilter.Method ("SetResult", 0, ParametersCompiled.CreateFullyResolved (bt.MemberDefinition.TypeParameters), btypes.Void); + set_result = new PredefinedMember (Module, bt, set_result_sign).Resolve (Location); + + var set_exception_sign = MemberFilter.Method ("SetException", 0, ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void); + set_exception = new PredefinedMember (Module, bt, set_exception_sign).Resolve (Location); + + var builder_factory_sign = MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, bt_inflated); + builder_factory = new PredefinedMember (Module, bt, builder_factory_sign).Resolve (Location); + if (builder_factory?.IsStatic == false) + throw new NotImplementedException ("report better error message"); + + var builder_start_sign = MemberFilter.Method ("Start", 1, new ParametersImported ( + new [] { + new ParameterData (null, Parameter.Modifier.REF), + }, + new [] { + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + }, false), + btypes.Void); + builder_start = new PredefinedMember (Module, bt, builder_start_sign).Resolve (Location); + + if (!istate_machine.Define ()) + return false; + + var set_statemachine_sign = MemberFilter.Method ("SetStateMachine", 0, ParametersCompiled.CreateFullyResolved (istate_machine.TypeSpec), btypes.Void); + set_statemachine = new PredefinedMember (Module, bt, set_statemachine_sign).Resolve (Location); ; + + var task_sign = MemberFilter.Property ("Task", return_type.MemberDefinition as TypeSpec); + task = new PredefinedMember (Module, bt, task_sign).Resolve (Location); + + if (set_result == null || set_exception == null || builder_factory == null || builder_start == null || set_statemachine == null || task == null || + !Module.PredefinedTypes.INotifyCompletion.Define ()) { + return false; + } + + has_task_return_type = return_type.IsGeneric; } else { - builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; - bf = pred_members.AsyncTaskMethodBuilderGenericCreate; - bs = pred_members.AsyncTaskMethodBuilderGenericStart; - sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; - se = pred_members.AsyncTaskMethodBuilderGenericSetException; - sm = pred_members.AsyncTaskMethodBuilderGenericSetStateMachine; - task = pred_members.AsyncTaskMethodBuilderGenericTask.Get (); - has_task_return_type = true; - } + PredefinedType builder_type; + PredefinedMember bf; + PredefinedMember bs; + PredefinedMember sr; + PredefinedMember se; + PredefinedMember sm; + var pred_members = Module.PredefinedMembers; + + if (return_type.Kind == MemberKind.Void) { + builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; + bf = pred_members.AsyncVoidMethodBuilderCreate; + bs = pred_members.AsyncVoidMethodBuilderStart; + sr = pred_members.AsyncVoidMethodBuilderSetResult; + se = pred_members.AsyncVoidMethodBuilderSetException; + sm = pred_members.AsyncVoidMethodBuilderSetStateMachine; + } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { + builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; + bf = pred_members.AsyncTaskMethodBuilderCreate; + bs = pred_members.AsyncTaskMethodBuilderStart; + sr = pred_members.AsyncTaskMethodBuilderSetResult; + se = pred_members.AsyncTaskMethodBuilderSetException; + sm = pred_members.AsyncTaskMethodBuilderSetStateMachine; + task = pred_members.AsyncTaskMethodBuilderTask.Get (); + } else { + builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; + bf = pred_members.AsyncTaskMethodBuilderGenericCreate; + bs = pred_members.AsyncTaskMethodBuilderGenericStart; + sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; + se = pred_members.AsyncTaskMethodBuilderGenericSetException; + sm = pred_members.AsyncTaskMethodBuilderGenericSetStateMachine; + task = pred_members.AsyncTaskMethodBuilderGenericTask.Get (); + has_task_return_type = true; + } - set_result = sr.Get (); - set_exception = se.Get (); - builder_factory = bf.Get (); - builder_start = bs.Get (); + set_result = sr.Get (); + set_exception = se.Get (); + builder_factory = bf.Get (); + builder_start = bs.Get (); - var istate_machine = Module.PredefinedTypes.IAsyncStateMachine; - var set_statemachine = sm.Get (); - - if (!builder_type.Define () || !istate_machine.Define () || set_result == null || builder_factory == null || - set_exception == null || set_statemachine == null || builder_start == null || - !Module.PredefinedTypes.INotifyCompletion.Define ()) { - Report.Error (1993, Location, - "Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?"); - return base.DoDefineMembers (); - } + set_statemachine = sm.Get (); + + if (!builder_type.Define () || !istate_machine.Define () || set_result == null || builder_factory == null || + set_exception == null || set_statemachine == null || builder_start == null || + !Module.PredefinedTypes.INotifyCompletion.Define ()) { + Report.Error (1993, Location, + "Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?"); + return base.DoDefineMembers (); + } - var bt = builder_type.TypeSpec; + bt = builder_type.TypeSpec; + } // // Inflate generic Task types @@ -825,9 +879,26 @@ namespace Mono.CSharp predefined = unsafeVersion ? pm.AsyncVoidMethodBuilderOnCompletedUnsafe : pm.AsyncVoidMethodBuilderOnCompleted; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { predefined = unsafeVersion ? pm.AsyncTaskMethodBuilderOnCompletedUnsafe : pm.AsyncTaskMethodBuilderOnCompleted; - } else { + } else if (return_type.IsGenericTask) { predefined = unsafeVersion ? pm.AsyncTaskMethodBuilderGenericOnCompletedUnsafe : pm.AsyncTaskMethodBuilderGenericOnCompleted; has_task_return_type = true; + } else { + var parameters = new ParametersImported ( + new [] { + new ParameterData (null, Parameter.Modifier.REF), + new ParameterData (null, Parameter.Modifier.REF) + }, + new [] { + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + new TypeParameterSpec (1, null, SpecialConstraint.None, Variance.None, null) + }, false); + + var on_completed_sign = unsafeVersion ? + MemberFilter.Method ("AwaitUnsafeOnCompleted", 2, parameters, Compiler.BuiltinTypes.Void) : + MemberFilter.Method ("AwaitOnCompleted", 2, parameters, Compiler.BuiltinTypes.Void); + + predefined = new PredefinedMember (Module, return_type.MemberDefinition.GetAsyncMethodBuilder (), on_completed_sign); + has_task_return_type = return_type.IsGeneric; } var on_completed = predefined.Resolve (Location); @@ -887,11 +958,14 @@ namespace Mono.CSharp // stateMachine.$builder.Start<{storey-type}>(ref stateMachine); // instance.AddressOf (ec, AddressOp.Store); - ec.Emit (OpCodes.Ldflda, builder_field); + + bool struct_builder = builder.MemberType.IsStruct; + + ec.Emit (struct_builder ? OpCodes.Ldflda : OpCodes.Ldfld, builder_field); if (Task != null) ec.Emit (OpCodes.Dup); instance.AddressOf (ec, AddressOp.Store); - ec.Emit (OpCodes.Call, builder_start.MakeGenericMethod (Module, instance.Type)); + ec.Emit (struct_builder ? OpCodes.Call : OpCodes.Callvirt, builder_start.MakeGenericMethod (Module, instance.Type)); // // Emits return stateMachine.$builder.Task; @@ -1029,4 +1103,20 @@ namespace Mono.CSharp EmitAssign (ec, new NullConstant (type, loc), false, false); } } + + static class TypeSpecAsyncExtensions + { + public static bool IsCustomTaskType (this TypeSpec type) + { + // LAMESPEC: Arity is not mentioned + if (type.Arity > 1) + return false; + + var amb = type.MemberDefinition.GetAsyncMethodBuilder (); + if (amb == null) + return false; + + return amb.Arity == type.Arity; + } + } } diff --git a/mcs/mcs/attribute.cs b/mcs/mcs/attribute.cs index 3ff2d68ccb5..83d403118ad 100644 --- a/mcs/mcs/attribute.cs +++ b/mcs/mcs/attribute.cs @@ -789,6 +789,17 @@ namespace Mono.CSharp { return ((BoolConstant) pos_args[0].Expr).Value; } + public TypeSpec GetAsyncMethodBuilderValue () + { + if (!arg_resolved) + Resolve (); + + if (resolve_error) + return null; + + return GetArgumentType (); + } + public TypeSpec GetCoClassAttributeValue () { if (!arg_resolved) @@ -1754,9 +1765,11 @@ namespace Mono.CSharp { // New in .NET 4.7 public readonly PredefinedTupleElementNamesAttribute TupleElementNames; + public readonly PredefinedAttribute AsyncMethodBuilder; // New in .NET 4.7.1 public readonly PredefinedAttribute IsReadOnly; + public readonly PredefinedAttribute IsByRefLike; // // Optional types which are used as types and for member lookup @@ -1837,8 +1850,10 @@ namespace Mono.CSharp { CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute"); CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute"); + AsyncMethodBuilder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "AsyncMethodBuilderAttribute"); TupleElementNames = new PredefinedTupleElementNamesAttribute (module, "System.Runtime.CompilerServices", "TupleElementNamesAttribute"); IsReadOnly = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IsReadOnlyAttribute"); + IsByRefLike = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IsByRefLikeAttribute"); // TODO: Should define only attributes which are used for comparison const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public | diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index 9afb32c6fe5..6b1adc297a3 100644 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -224,6 +224,24 @@ namespace Mono.CSharp } } + public void CloseContainerEarlyForReflectionEmit () + { + if (containers != null) { + foreach (TypeContainer tc in containers) { + // + // SRE requires due to internal checks that any field of enum type is + // baked. We close all enum types before closing any other types to + // workaround this limitation + // + if (tc.Kind == MemberKind.Enum) { + tc.CloseContainer (); + } else { + tc.CloseContainerEarlyForReflectionEmit (); + } + } + } + } + public virtual void CreateMetadataName (StringBuilder sb) { if (Parent != null && Parent.MemberName != null) @@ -1102,6 +1120,18 @@ namespace Mono.CSharp member.GenerateDocComment (builder); } + public TypeSpec GetAsyncMethodBuilder () + { + if (OptAttributes == null) + return null; + + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.AsyncMethodBuilder); + if (a == null) + return null; + + return a.GetAsyncMethodBuilderValue (); + } + public TypeSpec GetAttributeCoClass () { if (OptAttributes == null) @@ -2171,7 +2201,7 @@ namespace Mono.CSharp public override void Emit () { - if (Interfaces != null) { + if (Interfaces != null && (ModFlags & Modifiers.PRIVATE) == 0) { foreach (var iface in Interfaces) { if (iface.HasNamedTupleElement) { throw new NotImplementedException ("named tuples for .interfaceimpl"); @@ -3023,7 +3053,8 @@ namespace Mono.CSharp Modifiers.INTERNAL | Modifiers.UNSAFE | Modifiers.PRIVATE | - Modifiers.READONLY; + Modifiers.READONLY | + Modifiers.REF; public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs) : base (parent, name, attrs, MemberKind.Struct) @@ -3139,6 +3170,9 @@ namespace Mono.CSharp if ((ModFlags & Modifiers.READONLY) != 0) Module.PredefinedAttributes.IsReadOnly.EmitAttribute (TypeBuilder); + if ((ModFlags & Modifiers.REF) != 0) + Module.PredefinedAttributes.IsByRefLike.EmitAttribute (TypeBuilder); + CheckStructCycles (); base.Emit (); @@ -3213,6 +3247,10 @@ namespace Mono.CSharp protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) { var ifaces = base.ResolveBaseTypes (out base_class); + if (ifaces != null && (ModFlags & Modifiers.REF) != 0) { + Report.Error (8343, Location, "`{0}': ref structs cannot implement interfaces", GetSignatureForError ()); + } + base_type = Compiler.BuiltinTypes.ValueType; return ifaces; } @@ -3915,7 +3953,7 @@ namespace Mono.CSharp protected void IsTypePermitted () { - if (MemberType.IsSpecialRuntimeType) { + if (MemberType.IsSpecialRuntimeType || MemberType.IsByRefLike) { if (Parent is StateMachine) { Report.Error (4012, Location, "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators", @@ -3924,6 +3962,19 @@ namespace Mono.CSharp Report.Error (4013, Location, "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions", MemberType.GetSignatureForError ()); + } else if (MemberType.IsByRefLike) { + if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) + return; + + if ((ModFlags & Modifiers.AutoProperty) == 0 && this is Property) + return; + + if ((ModFlags & Modifiers.STATIC) == 0 && (Parent.ModFlags & Modifiers.REF) != 0) + return; + + Report.Error (8345, Location, + "Field or auto-implemented property cannot be of type `{0}' unless it is an instance member of a ref struct", + MemberType.GetSignatureForError ()); } else { Report.Error (610, Location, "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ()); diff --git a/mcs/mcs/const.cs b/mcs/mcs/const.cs index 046aec24c1b..658f15ec57a 100644 --- a/mcs/mcs/const.cs +++ b/mcs/mcs/const.cs @@ -206,7 +206,9 @@ namespace Mono.CSharp { c = field.ConvertInitializer (rc, c); if (c == null) { - if (TypeSpec.IsReferenceType (field.MemberType)) + if (expr is DefaultLiteralExpression) { + // It's handled bellow in New.Constantify + } else if (TypeSpec.IsReferenceType (field.MemberType)) Error_ConstantCanBeInitializedWithNullOnly (rc, field.MemberType, expr.Location, GetSignatureForError ()); else if (!(expr is Constant)) Error_ExpressionMustBeConstant (rc, expr.Location, GetSignatureForError ()); diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs index b11477c1043..ae153fc49e8 100644 --- a/mcs/mcs/convert.cs +++ b/mcs/mcs/convert.cs @@ -392,6 +392,9 @@ namespace Mono.CSharp { if (!TypeSpec.IsValueType (expr_type)) return null; + if (expr_type.IsByRefLike) + return null; + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); case BuiltinTypeSpec.Type.Enum: @@ -816,7 +819,7 @@ namespace Mono.CSharp { if (expr_type == target_type) return true; - if (expr_type == InternalType.ThrowExpr) + if (expr_type == InternalType.ThrowExpr || expr_type == InternalType.DefaultType) return target_type.Kind != MemberKind.InternalCompilerType; if (target_type.IsNullableType) @@ -1478,6 +1481,10 @@ namespace Mono.CSharp { return target_type.Kind == MemberKind.InternalCompilerType ? null : EmptyCast.Create (expr, target_type); } + if (expr_type == InternalType.DefaultType) { + return new DefaultValueExpression (new TypeExpression (target_type, expr.Location), expr.Location).Resolve (ec); + } + if (target_type.IsNullableType) return ImplicitNulableConversion (ec, expr, target_type); @@ -1967,7 +1974,7 @@ namespace Mono.CSharp { // From object or dynamic to any reference type or value type (unboxing) // if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { - if (target_type.IsPointer) + if (target_type.IsPointer || target_type.IsByRefLike) return null; return diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 2868d2fd8f6..4d6fcb44c0d 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -169,7 +169,8 @@ namespace Mono.CSharp %token CONST %token CONTINUE %token DECIMAL -%token DEFAULT +%token DEFAULT +%token DEFAULT_VALUE %token DELEGATE %token DO %token DOUBLE @@ -336,6 +337,7 @@ namespace Mono.CSharp %token DEFAULT_COLON %token OPEN_BRACKET_EXPR %token OPEN_PARENS_DECONSTRUCT +%token REF_STRUCT // Make the parser go into eval mode parsing (statements and compilation units). %token EVAL_STATEMENT_PARSER @@ -863,7 +865,7 @@ attribute_arguments } Arguments args = ((Arguments) o [0]); - if (args.Count > 0 && !($3 is NamedArgument) && args [args.Count - 1] is NamedArgument) + if (lang_version < LanguageVersion.V_7_2 && args.Count > 0 && !($3 is NamedArgument) && args [args.Count - 1] is NamedArgument) Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) $3); @@ -1015,17 +1017,34 @@ primary_constructor_body } ; +struct_keyword + : STRUCT + { + $$ = null; + } + | REF_STRUCT + { + if (lang_version < LanguageVersion.V_7_2) { + FeatureIsNotAvailable (GetLocation ($1), "ref structs"); + } + + $$ = this; + } + ; + struct_declaration : opt_attributes opt_modifiers opt_partial - STRUCT + struct_keyword type_declaration_name { var mods = (Modifiers) $2; if ((mods & Modifiers.READONLY) != 0 && lang_version < LanguageVersion.V_7_2) { FeatureIsNotAvailable (GetLocation ($4), "readonly structs"); } + if ($4 != null) + mods |= Modifiers.REF; lexer.ConstraintsParsing = true; valid_param_mod = ParameterModifierType.PrimaryConstructor; @@ -1071,7 +1090,7 @@ struct_declaration } $$ = pop_current_class (); } - | opt_attributes opt_modifiers opt_partial STRUCT error + | opt_attributes opt_modifiers opt_partial struct_keyword error { Error_SyntaxError (yyToken); } @@ -1384,6 +1403,18 @@ ref_member_type $$ = new ReferenceTypeExpr ((FullNamedExpression) $3, GetLocation ($1)); } + | REF READONLY + { + lexer.parsing_generic_declaration = true; + } + type + { + if (lang_version < LanguageVersion.V_7_2) { + FeatureIsNotAvailable (GetLocation ($2), "readonly references"); + } + + $$ = new ReferenceTypeExpr ((FullNamedExpression) $4, true, GetLocation ($1)); + } ; method_header @@ -3448,6 +3479,7 @@ primary_expression | anonymous_method_expression | undocumented_expressions | interpolated_string + | default_literal ; type_name_expression @@ -3824,7 +3856,7 @@ argument_list | argument_list COMMA argument { Arguments list = (Arguments) $1; - if (list [list.Count - 1] is NamedArgument) + if (lang_version < LanguageVersion.V_7_2 && list [list.Count - 1] is NamedArgument) Error_NamedArgumentExpected ((NamedArgument) list [list.Count - 1]); list.Add ((Argument) $3); @@ -3969,7 +4001,7 @@ expression_list_arguments | expression_list_arguments COMMA expression_list_argument { Arguments args = (Arguments) $1; - if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) + if (lang_version < LanguageVersion.V_7_2 && args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) $3); @@ -4386,7 +4418,7 @@ anonymous_method_signature ; default_value_expression - : DEFAULT open_parens_any type CLOSE_PARENS + : DEFAULT_VALUE open_parens_any type CLOSE_PARENS { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "default value expression"); @@ -4396,6 +4428,16 @@ default_value_expression } ; +default_literal + : DEFAULT + { + if (lang_version < LanguageVersion.V_7_1) + FeatureIsNotAvailable (GetLocation ($1), "default literal"); + + $$ = new DefaultLiteralExpression (GetLocation ($1)); + } + ; + unary_expression : primary_expression | BANG prefixed_unary_expression @@ -4750,7 +4792,7 @@ pattern_list | pattern_list COMMA pattern_argument { Arguments args = (Arguments) $1; - if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) + if (lang_version < LanguageVersion.V_7_2 && args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) $3); @@ -5067,17 +5109,25 @@ assignment_expression $$ = new CompoundAssign (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3); lbag.AddLocation ($$, GetLocation ($2)); } - | OPEN_PARENS_DECONSTRUCT deconstruct_exprs CLOSE_PARENS ASSIGN expression + | OPEN_PARENS_DECONSTRUCT deconstruct_assignment CLOSE_PARENS ASSIGN expression { if (lang_version < LanguageVersion.V_7) FeatureIsNotAvailable (GetLocation ($1), "tuples"); - var exprs = (List) $2; + var exprs = (List) $2; + $$ = new TupleDeconstruct (exprs, (Expression) $5, GetLocation ($4)); + } + | OPEN_PARENS_DECONSTRUCT deconstruct_declaration CLOSE_PARENS ASSIGN expression + { + if (lang_version < LanguageVersion.V_7) + FeatureIsNotAvailable (GetLocation ($1), "tuples"); + + var exprs = (List) $2; $$ = new TupleDeconstruct (exprs, (Expression) $5, GetLocation ($4)); } ; -deconstruct_exprs +deconstruct_assignment : expression COMMA expression { $$ = new List () { @@ -5085,7 +5135,7 @@ deconstruct_exprs (Expression) $3 }; } - | deconstruct_exprs COMMA expression + | deconstruct_assignment COMMA expression { var src = (List) $1; src.Add ((Expression) $3); @@ -5093,6 +5143,43 @@ deconstruct_exprs } ; +deconstruct_declaration + : variable_type identifier_inside_body + { + var lt = (LocatedToken) $2; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + $$ = new List (2) { + new BlockVariable ((FullNamedExpression) $1, li) + }; + } + | deconstruct_declaration COMMA variable_type identifier_inside_body + { + var lt = (LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + + var src = (List) $1; + src.Add (new BlockVariable ((FullNamedExpression) $3, li)); + $$ = src; + } + | deconstruct_declaration COMMA identifier_inside_body + { + var lt = (LocatedToken) $3; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + + if (lt.Value != "_") { + report.Error (8184, lt.Location, "A deconstruction cannot mix declarations and expressions on the left-hand-side"); + } else { + li.Type = InternalType.Discard; + } + + var src = (List) $1; + src.Add (new BlockVariable (new TypeExpression (li.Type, lt.Location), li)); + $$ = src; + } + ; + lambda_parameter_list : lambda_parameter { @@ -6008,6 +6095,28 @@ block_variable_declaration lbag.AddLocation ($$, GetLocation ($7)); } } + | REF READONLY variable_type identifier_inside_body + { + if (lang_version < LanguageVersion.V_7_2) { + FeatureIsNotAvailable (GetLocation ($2), "readonly references"); + } + + var lt = (LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ByRef | LocalVariable.Flags.ReadonlyMask, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariable ((FullNamedExpression) $3, li); + } + opt_local_variable_initializer opt_variable_declarators SEMICOLON + { + $$ = current_variable; + current_variable = null; + if ($6 != null) { + lbag.AddLocation ($$, PopLocation (), GetLocation ($8)); + } else { + report.Error (8174, GetLocation ($3), "A declaration of a by-reference variable must have an initializer"); + lbag.AddLocation ($$, GetLocation ($8)); + } + } ; opt_local_variable_initializer @@ -7731,7 +7840,7 @@ void Warning_EmptyStatement (Location loc) void Error_NamedArgumentExpected (NamedArgument a) { - report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); + report.Error (1738, a.Location, "Named arguments must appear after the positional arguments when using language version older than 7.2"); } void Error_MissingInitializer (Location loc) @@ -8255,6 +8364,7 @@ static string GetTokenName (int token) case Token.CONTINUE: return "continue"; case Token.DEFAULT: + case Token.DEFAULT_VALUE: return "default"; case Token.DELEGATE: return "delegate"; @@ -8334,6 +8444,7 @@ static string GetTokenName (int token) case Token.STATIC: return "static"; case Token.STRUCT: + case Token.REF_STRUCT: return "struct"; case Token.SWITCH: return "switch"; diff --git a/mcs/mcs/cs-tokenizer.cs b/mcs/mcs/cs-tokenizer.cs index d6d00d31400..37edb5c1224 100644 --- a/mcs/mcs/cs-tokenizer.cs +++ b/mcs/mcs/cs-tokenizer.cs @@ -716,9 +716,18 @@ namespace Mono.CSharp res = Token.EXTERN_ALIAS; break; case Token.DEFAULT: - if (peek_token () == Token.COLON) { - token (); - res = Token.DEFAULT_COLON; + switch (peek_token ()) { + case Token.COLON: + // Special case: foo == null ? default : 1; + if (current_token != Token.INTERR) { + token (); + res = Token.DEFAULT_COLON; + } + break; + case Token.OPEN_PARENS: + case Token.OPEN_PARENS_CAST: + res = Token.DEFAULT_VALUE; + break; } break; case Token.WHEN: @@ -812,10 +821,12 @@ namespace Mono.CSharp PushPosition (); next_token = token (); - bool ok = (next_token == Token.CLASS) || - (next_token == Token.STRUCT) || - (next_token == Token.INTERFACE) || - (next_token == Token.VOID); + bool ok = + next_token == Token.CLASS || + next_token == Token.STRUCT || + next_token == Token.INTERFACE || + next_token == Token.VOID || + next_token == Token.REF_STRUCT; PopPosition (); @@ -903,6 +914,12 @@ namespace Mono.CSharp break; } + break; + case Token.REF: + if (peek_token () == Token.STRUCT) { + token (); + res = Token.REF_STRUCT; + } break; } @@ -1094,6 +1111,7 @@ namespace Mono.CSharp case Token.UNCHECKED: case Token.UNSAFE: case Token.DEFAULT: + case Token.DEFAULT_VALUE: case Token.AWAIT: // @@ -1273,14 +1291,21 @@ namespace Mono.CSharp return false; case Token.OPEN_PARENS: - if (!parsing_generic_declaration) - return false; - + int parens_count = 1; while (true) { switch (token ()) { case Token.COMMA: // tuple declaration after < - return true; + if (parens_count == 1) + return true; + continue; + case Token.OPEN_PARENS: + ++parens_count; + continue; + case Token.CLOSE_PARENS: + if (--parens_count <= 0) + return false; + continue; case Token.OP_GENERICS_GT: case Token.EOF: return false; @@ -1380,6 +1405,7 @@ namespace Mono.CSharp case Token.NEW: case Token.INTERPOLATED_STRING: case Token.THROW: + case Token.DEFAULT_COLON: next_token = Token.INTERR; break; @@ -3502,6 +3528,7 @@ namespace Mono.CSharp case Token.SWITCH: case Token.USING: case Token.DEFAULT: + case Token.DEFAULT_VALUE: case Token.DELEGATE: case Token.OP_GENERICS_GT: case Token.REFVALUE: @@ -3963,26 +3990,29 @@ namespace Mono.CSharp { int d; - // Save current position and parse next token. - PushPosition (); - int generic_dimension = 0; - if (parse_less_than (ref generic_dimension)) { - if (parsing_generic_declaration && (parsing_generic_declaration_doc || token () != Token.DOT)) { - d = Token.OP_GENERICS_LT_DECL; - } else { - if (generic_dimension > 0) { - val = generic_dimension; - DiscardPosition (); - return Token.GENERIC_DIMENSION; - } + if (current_token != Token.OPERATOR) { + // Save current position and parse next token. + PushPosition (); + int generic_dimension = 0; + if (parse_less_than (ref generic_dimension)) { + if (parsing_generic_declaration && (parsing_generic_declaration_doc || token () != Token.DOT)) { + d = Token.OP_GENERICS_LT_DECL; + } else { + if (generic_dimension > 0) { + val = generic_dimension; + DiscardPosition (); + return Token.GENERIC_DIMENSION; + } - d = Token.OP_GENERICS_LT; + d = Token.OP_GENERICS_LT; + } + PopPosition (); + return d; } + PopPosition (); - return d; } - PopPosition (); parsing_generic_less_than = 0; d = peek_char (); diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 80eb7e265f1..52cee8f3455 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -188,8 +188,8 @@ namespace Mono.CSharp { CheckProtectedModifier (); - if (Compiler.Settings.StdLib && ret_type.IsSpecialRuntimeType) { - Method.Error1599 (Location, ret_type, Report); + if (ret_type.IsSpecialRuntimeType && Compiler.Settings.StdLib) { + Method.Error_ReturnTypeCantBeRefAny (Location, ret_type, Report); return false; } @@ -338,6 +338,8 @@ namespace Mono.CSharp { Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder); } else if (rtype.HasDynamicElement) { Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, rtype, Location); + } else if (rtype is ReadOnlyReferenceContainer) { + Module.PredefinedAttributes.IsReadOnly.EmitAttribute (CreateReturnBuilder ().Builder); } if (rtype.HasNamedTupleElement) { @@ -603,8 +605,14 @@ namespace Mono.CSharp { } var expr = method_group.InstanceExpression; - if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type))) + if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type))) { + if (expr.Type.IsByRefLike || expr.Type.IsSpecialRuntimeType) { + // CSC: Should be better error code + Error_ConversionFailed (ec, delegate_method, null); + } + method_group.InstanceExpression = new BoxedCast (expr, ec.BuiltinTypes.Object); + } eclass = ExprClass.Value; return this; diff --git a/mcs/mcs/dynamic.cs b/mcs/mcs/dynamic.cs index fd4662b2fed..f8314b2f3cd 100644 --- a/mcs/mcs/dynamic.cs +++ b/mcs/mcs/dynamic.cs @@ -279,11 +279,19 @@ namespace Mono.CSharp protected bool DoResolveCore (ResolveContext rc) { + int i = 0; foreach (var arg in arguments) { if (arg.Type == InternalType.VarOutType) { // Should be special error message about dynamic dispatch rc.Report.Error (8197, arg.Expr.Location, "Cannot infer the type of implicitly-typed out variable `{0}'", ((DeclarationExpression) arg.Expr).Variable.Name); + } else if (arg.Type == InternalType.DefaultType) { + rc.Report.Error (8311, arg.Expr.Location, "Cannot use a default literal as an argument to a dynamically dispatched operation"); } + + // Forced limitation because Microsoft.CSharp needs to catch up + if (i > 0 && arguments [i - 1] is NamedArgument && !(arguments [i] is NamedArgument)) + rc.Report.Error (8324, loc, "Named argument specifications must appear after all fixed arguments have been specified in a dynamic invocation"); + ++i; } if (rc.CurrentTypeParameters != null && rc.CurrentTypeParameters[0].IsMethodTypeParameter) diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 34ff9a30dab..20ee9e73b19 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -255,7 +255,7 @@ namespace Mono.CSharp { public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name) { - rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name); + rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be a constant or default value", e_name); } public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name) @@ -2957,6 +2957,13 @@ namespace Mono.CSharp { if ((restrictions & MemberLookupRestrictions.NameOfExcluded) == 0 && Name == "nameof") return new NameOf (this); + if ((restrictions & MemberLookupRestrictions.ReadAccess) == 0 && Name == "_") { + if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_7) + rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, loc, "discards"); + + return new Discard (loc).Resolve (rc); + } + if (errorMode) { if (variable_found) { rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name); @@ -4029,6 +4036,13 @@ namespace Mono.CSharp { return Methods.First ().GetSignatureForError (); } + static MethodSpec CandidateDevirtualization (TypeSpec type, MethodSpec method) + { + // Assumes no generics get involved + var filter = new MemberFilter (method.Name, method.Arity, MemberKind.Method, method.Parameters, null); + return MemberCache.FindMember (type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly | BindingRestriction.DeclaredOnly) as MethodSpec; + } + public override Expression CreateExpressionTree (ResolveContext ec) { if (best_candidate == null) { @@ -4177,6 +4191,22 @@ namespace Mono.CSharp { } InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup | ResolveFlags.Type); + + var expr_type = InstanceExpression.Type; + if ((expr_type.IsByRefLike || expr_type.IsSpecialRuntimeType) && best_candidate.DeclaringType != expr_type) { + MethodSpec devirt = null; + if ((best_candidate.Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0) { + devirt = CandidateDevirtualization (expr_type, best_candidate); + } + + if (devirt == null) { + // CSC: Should be better error message + ec.Report.Error (29, InstanceExpression.Location, "Cannot implicitly convert type `{0}' to `{1}'", + InstanceExpression.Type.GetSignatureForError (), best_candidate.DeclaringType.GetSignatureForError ()); + } else { + best_candidate = devirt; + } + } } } @@ -5419,7 +5449,7 @@ namespace Mono.CSharp { } if (arg_type != parameter) { - if (arg_type == InternalType.VarOutType) + if (arg_type == InternalType.VarOutType || arg_type == InternalType.Discard) return 0; var ref_arg_type = arg_type as ReferenceContainer; @@ -6028,6 +6058,11 @@ namespace Mono.CSharp { continue; } + if (arg_type == InternalType.Discard) { + a.Expr.Type = pt; + continue; + } + var ref_arg_type = arg_type as ReferenceContainer; if (ref_arg_type != null) { if (ref_arg_type.Element != pt) @@ -6061,9 +6096,15 @@ namespace Mono.CSharp { else ec.Report.SymbolRelatedToPreviousError (member); - ec.Report.Error (1744, na.Location, - "Named argument `{0}' cannot be used for a parameter which has positional argument specified", - na.Name); + if (name_index > a_idx) { + ec.Report.Error (8323, na.Location, + "Named argument `{0}' is used out of position but is followed by positional argument", + na.Name); + } else { + ec.Report.Error (1744, na.Location, + "Named argument `{0}' cannot be used for a parameter which has positional argument specified", + na.Name); + } } } @@ -7350,6 +7391,9 @@ namespace Mono.CSharp { if (!ResolveGetter (ec)) return null; + if (type.Kind == MemberKind.ByRef) + return ByRefDereference.Create (this).Resolve (ec); + return this; } @@ -7359,12 +7403,11 @@ namespace Mono.CSharp { Error_NullPropagatingLValue (rc); if (right_side == EmptyExpression.OutAccess) { - if (best_candidate?.MemberType.Kind == MemberKind.ByRef) { - if (Arguments?.ContainsEmitWithAwait () == true) { - rc.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference", - GetSignatureForError ()); - } + if (OverloadResolve (rc, null) == null) + return null; + if (best_candidate?.MemberType.Kind == MemberKind.ByRef) { + getter = CandidateToBaseOverride (rc, best_candidate.Get); return this; } @@ -7396,7 +7439,7 @@ namespace Mono.CSharp { if (best_candidate.MemberType.Kind == MemberKind.ByRef) { getter = CandidateToBaseOverride (rc, best_candidate.Get); - return ByRefDereference.Create(this).Resolve(rc); + return ByRefDereference.Create (this).Resolve (rc); } rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)", diff --git a/mcs/mcs/eval.cs b/mcs/mcs/eval.cs index 60e0c6d64a0..075697bb1df 100644 --- a/mcs/mcs/eval.cs +++ b/mcs/mcs/eval.cs @@ -788,6 +788,7 @@ namespace Mono.CSharp return null; } + module.CloseContainerEarlyForReflectionEmit (); module.CloseContainer (); if (host != null) host.CloseContainer (); diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 732ee3ee934..518ccc8ef43 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1220,6 +1220,7 @@ namespace Mono.CSharp expr = expr.ResolveLValue (ec, expr); } else { ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer"); + return null; } // @@ -1477,6 +1478,11 @@ namespace Mono.CSharp return null; } + if (expr.Type == InternalType.DefaultType) { + Error_OperatorCannotBeApplied (rc, loc, OperatorName, expr.Type); + return null; + } + return this; } @@ -4304,9 +4310,32 @@ namespace Mono.CSharp CheckOutOfRangeComparison (ec, rc, left.Type); } - if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic || right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + var ltype = left.Type; + var rtype = right.Type; + if (ltype.BuiltinType == BuiltinTypeSpec.Type.Dynamic || rtype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) return DoResolveDynamic (ec); + // + // Only default with == and != is explicitly allowed + // + if (ltype == InternalType.DefaultType || rtype == InternalType.DefaultType) { + if ((Oper & Operator.EqualityMask) == 0) { + ec.Report.Error (8310, loc, "Operator `{0}' cannot be applied to operand `default'", OperName (Oper)); + return null; + } + + if (ltype == rtype) { + ec.Report.Error (8315, loc, "Operator `{0}' is ambiguous on operands `default' and `default'", OperName (Oper)); + return null; + } + + if (rtype == InternalType.DefaultType) { + right = new DefaultValueExpression (new TypeExpression (ltype, right.Location), right.Location).Resolve (ec); + } else { + left = new DefaultValueExpression (new TypeExpression (rtype, left.Location), left.Location).Resolve (ec); + } + } + return DoResolveCore (ec, left, right); } @@ -6744,10 +6773,14 @@ namespace Mono.CSharp ec.Report.Error (1764, loc, "Cannot use fixed variable `{0}' inside an anonymous method, lambda expression or query expression", GetSignatureForError ()); - } else if (local_info.IsByRef) { - ec.Report.Error (8175, loc, - "Cannot use by-reference variable `{0}' inside an anonymous method, lambda expression, or query expression", - GetSignatureForError ()); + } else if (local_info.IsByRef || local_info.Type.IsByRefLike) { + if (ec.CurrentAnonymousMethod is StateMachineInitializer) { + // It's reported later as 4012/4013 + } else { + ec.Report.Error (8175, loc, + "Cannot use by-reference variable `{0}' inside an anonymous method, lambda expression, or query expression", + GetSignatureForError ()); + } } if (ec.IsVariableCapturingRequired) { @@ -6783,7 +6816,9 @@ namespace Mono.CSharp local_info.SetIsUsed (); if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) { - if (rhs == EmptyExpression.LValueMemberAccess) { + if (local_info.IsByRef) { + // OK because it cannot be reassigned + } else if (rhs == EmptyExpression.LValueMemberAccess) { // CS1654 already reported } else { int code; @@ -7175,8 +7210,7 @@ namespace Mono.CSharp { var sn = expr as SimpleName; if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) { - var targets = new List (arguments.Count); - var variables = new List (arguments.Count); + var variables = new List (arguments.Count); foreach (var arg in arguments) { var arg_sn = arg.Expr as SimpleName; if (arg_sn == null || arg_sn.Arity != 0) { @@ -7186,12 +7220,10 @@ namespace Mono.CSharp var lv = new LocalVariable (rc.CurrentBlock, arg_sn.Name, arg.Expr.Location); rc.CurrentBlock.AddLocalName (lv); - variables.Add (lv); - - targets.Add (new LocalVariableReference (lv, arg_sn.Location)); + variables.Add (new BlockVariable (new VarExpr (lv.Location), lv)); } - var res = new TupleDeconstruct (targets, variables, right_side, loc); + var res = new TupleDeconstruct (variables, right_side, loc); return res.Resolve (rc); } @@ -7306,15 +7338,8 @@ namespace Mono.CSharp eclass = ExprClass.Value; - if (type.Kind == MemberKind.ByRef) { - if (rhs == null && arguments?.ContainsEmitWithAwait () == true) { - ec.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference", - GetSignatureForError ()); - } - - if (rhs != EmptyExpression.OutAccess) - return ByRefDereference.Create (this).Resolve (ec); - } + if (type.Kind == MemberKind.ByRef && rhs != EmptyExpression.OutAccess) + return ByRefDereference.Create (this).Resolve (ec); return this; } @@ -9034,7 +9059,7 @@ namespace Mono.CSharp if (eclass == ExprClass.Unresolved) ResolveBase (ec); - if (type.IsClass || type.IsReadOnly) { + if (type.IsClass || (type.IsReadOnly && !ec.HasSet (ResolveContext.Options.ConstructorScope))) { if (right_side == EmptyExpression.UnaryAddress) ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only"); else if (right_side == EmptyExpression.OutAccess) @@ -9908,7 +9933,7 @@ namespace Mono.CSharp public static bool IsValidDotExpression (TypeSpec type) { const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum | - MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType; + MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType | MemberKind.ByRef; return (type.Kind & dot_kinds) != 0 || type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; } @@ -11614,7 +11639,7 @@ namespace Mono.CSharp } if (single_spec != null && single_spec.Dimension > 0) { - if (type.IsSpecialRuntimeType) { + if (type.IsSpecialRuntimeType || type.IsByRefLike) { ec.Module.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", type.GetSignatureForError ()); } else if (type.IsStatic) { ec.Module.Compiler.Report.SymbolRelatedToPreviousError (type); @@ -11650,6 +11675,13 @@ namespace Mono.CSharp class ReferenceTypeExpr : TypeExpr { FullNamedExpression element; + readonly bool readOnly; + + public ReferenceTypeExpr (FullNamedExpression element, bool readOnly, Location loc) + : this (element, loc) + { + this.readOnly = readOnly; + } public ReferenceTypeExpr (FullNamedExpression element, Location loc) { @@ -11664,14 +11696,17 @@ namespace Mono.CSharp return null; eclass = ExprClass.Type; - type = ReferenceContainer.MakeType (mc.Module, type); + type = readOnly ? + ReadOnlyReferenceContainer.MakeType (mc.Module, type) : + ReferenceContainer.MakeType (mc.Module, type); return type; } public override string GetSignatureForError () { - return "ref " + element.GetSignatureForError (); + var prefix = readOnly ? "ref " : "ref readonly "; + return prefix + element.GetSignatureForError (); } public override object Accept (StructuralVisitor visitor) @@ -11783,6 +11818,7 @@ namespace Mono.CSharp TypeSpec otype; Expression texpr; Expression count; + MethodSpec ctor; public StackAlloc (Expression type, Expression count, Location l) { @@ -11852,6 +11888,11 @@ namespace Mono.CSharp int size = BuiltinTypeSpec.GetSize (otype); count.Emit (ec); + bool count_on_stack = false; + if (ctor != null && !ExpressionAnalyzer.IsInexpensiveLoad (count)) { + ec.Emit (OpCodes.Dup); + count_on_stack = true; + } if (size == 0) ec.Emit (OpCodes.Sizeof, otype); @@ -11860,6 +11901,19 @@ namespace Mono.CSharp ec.Emit (OpCodes.Mul_Ovf_Un); ec.Emit (OpCodes.Localloc); + + if (ctor != null) { + if (!count_on_stack) + count.Emit (ec); + ec.Emit (OpCodes.Newobj, ctor); + } + } + + public override void Error_ValueCannotBeConverted (ResolveContext rc, TypeSpec target, bool expl) + { + var etype = ((PointerContainer)type).Element; + rc.Report.Error (8346, loc, "Cannot convert a stackalloc expression of type `{0}' to type `{1}'", + etype.GetSignatureForError (), target.GetSignatureForError ()); } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -11873,6 +11927,16 @@ namespace Mono.CSharp { return visitor.Visit (this); } + + public bool ResolveSpanConversion (ResolveContext rc, TypeSpec spanType) + { + ctor = MemberCache.FindMember (spanType, MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (PointerContainer.MakeType (rc.Module, rc.Module.Compiler.BuiltinTypes.Void), rc.Module.Compiler.BuiltinTypes.Int)), BindingRestriction.DeclaredOnly) as MethodSpec; + if (ctor == null) + return false; + + this.type = spanType; + return true; + } } // @@ -13093,6 +13157,12 @@ namespace Mono.CSharp expr.Emit (ec); } + public override Expression CreateExpressionTree (ResolveContext rc) + { + rc.Report.Error (8153, Location, "An expression tree lambda cannot contain a call to a method, property, or indexer that returns by reference"); + return null; + } + public void Emit (EmitContext ec, bool leave_copy) { Emit (ec); @@ -13133,6 +13203,11 @@ namespace Mono.CSharp public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) { + if (expr.ContainsEmitWithAwait ()) { + rc.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference", + expr.GetSignatureForError ()); + } + return DoResolve (rc); } @@ -13149,4 +13224,98 @@ namespace Mono.CSharp return visitor.Visit (this); } } + + class DefaultLiteralExpression : Expression + { + public DefaultLiteralExpression (Location loc) + { + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException (); + } + + protected override Expression DoResolve (ResolveContext rc) + { + type = InternalType.DefaultType; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException (); + } + } + + class Discard : Expression, IAssignMethod, IMemoryLocation + { + public Discard (Location loc) + { + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext rc) + { + rc.Report.Error (8207, loc, "An expression tree cannot contain a discard"); + return null; + } + + protected override Expression DoResolve (ResolveContext rc) + { + type = InternalType.Discard; + eclass = ExprClass.Variable; + return this; + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + if (right_side.Type == InternalType.DefaultType) { + rc.Report.Error (8183, loc, "Cannot infer the type of implicitly-typed discard"); + type = InternalType.ErrorType; + return this; + } + + if (right_side.Type.Kind == MemberKind.Void) { + rc.Report.Error (8209, loc, "Cannot assign void to a discard"); + type = InternalType.ErrorType; + return this; + } + + if (right_side != EmptyExpression.OutAccess) { + type = right_side.Type; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) + { + if (leave_copy) + source.Emit (ec); + else + source.EmitSideEffect (ec); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + var temp = ec.GetTemporaryLocal (type); + ec.Emit (OpCodes.Ldloca, temp); + + // TODO: Should free it on next statement but don't have mechanism for that yet + // ec.FreeTemporaryLocal (temp, type); + } + } } diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index 625cd0c773f..ec2965df63b 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -693,6 +693,11 @@ namespace Mono.CSharp { GetSignatureForError (), mc.GetSignatureForError (), input_variance, gtype_variance, parameters); } + public TypeSpec GetAsyncMethodBuilder () + { + return null; + } + public TypeSpec GetAttributeCoClass () { return null; @@ -2292,7 +2297,7 @@ namespace Mono.CSharp { ok = false; } - if (te.IsPointer || te.IsSpecialRuntimeType) { + if (te.IsPointer || te.IsSpecialRuntimeType || te.IsByRefLike) { ec.Module.Compiler.Report.Error (306, args[i].Location, "The type `{0}' may not be used as a type argument", te.GetSignatureForError ()); @@ -3102,7 +3107,7 @@ namespace Mono.CSharp { // // Some types cannot be used as type arguments // - if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType || + if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType || bound.Type.IsByRefLike || bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType || bound.Type == InternalType.ThrowExpr) return; @@ -3110,6 +3115,9 @@ namespace Mono.CSharp { if (bound.Type.IsTupleType && TupleLiteral.ContainsNoTypeElement (bound.Type)) return; + if (bound.Type == InternalType.DefaultType) + return; + var a = bounds [index]; if (a == null) { a = new List (2); diff --git a/mcs/mcs/import.cs b/mcs/mcs/import.cs index 1cddf7c01f4..f7c4fd74b08 100644 --- a/mcs/mcs/import.cs +++ b/mcs/mcs/import.cs @@ -975,6 +975,10 @@ namespace Mono.CSharp mod |= Modifiers.READONLY; } + if (HasAttribute (CustomAttributeData.GetCustomAttributes (type), "IsByRefLikeAttribute", CompilerServicesNamespace)) { + mod |= Modifiers.REF; + } + break; } } @@ -1401,6 +1405,7 @@ namespace Mono.CSharp public string DefaultIndexerName; public bool? CLSAttributeValue; public TypeSpec CoClass; + public TypeSpec AsyncMethodBuilder; static bool HasMissingType (ConstructorInfo ctor) { @@ -1522,6 +1527,20 @@ namespace Mono.CSharp bag.CoClass = importer.ImportType ((MetaType) a.ConstructorArguments[0].Value); continue; } + + if (name == "AsyncMethodBuilderAttribute") { + if (dt.Namespace != "System.Runtime.CompilerServices") + continue; + + if (HasMissingType (a.Constructor)) + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.AsyncMethodBuilder = importer.ImportType ((MetaType)a.ConstructorArguments [0].Value); + continue; + } } } @@ -2129,6 +2148,14 @@ namespace Mono.CSharp } } + public TypeSpec GetAsyncMethodBuilder () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.AsyncMethodBuilder; + } + public TypeSpec GetAttributeCoClass () { if (cattrs == null) @@ -2445,6 +2472,11 @@ namespace Mono.CSharp #endregion + public TypeSpec GetAsyncMethodBuilder () + { + return null; + } + public TypeSpec GetAttributeCoClass () { return null; diff --git a/mcs/mcs/membercache.cs b/mcs/mcs/membercache.cs index eebf71b844b..ca05d2d7afc 100644 --- a/mcs/mcs/membercache.cs +++ b/mcs/mcs/membercache.cs @@ -309,7 +309,6 @@ namespace Mono.CSharp { // if (!BuiltinTypeSpec.IsPrimitiveType (dt) || dt.BuiltinType == BuiltinTypeSpec.Type.Char) { switch (dt.BuiltinType) { - case BuiltinTypeSpec.Type.String: case BuiltinTypeSpec.Type.Delegate: case BuiltinTypeSpec.Type.MulticastDelegate: break; @@ -317,6 +316,9 @@ namespace Mono.CSharp { if (name == Operator.GetMetadataName (Operator.OpType.Implicit) || name == Operator.GetMetadataName (Operator.OpType.Explicit)) { state |= StateFlags.HasConversionOperator; } else { + if (dt.BuiltinType == BuiltinTypeSpec.Type.String) + break; + state |= StateFlags.HasUserOperator; } diff --git a/mcs/mcs/method.cs b/mcs/mcs/method.cs index ccd4898e91c..1fca10dd6d0 100644 --- a/mcs/mcs/method.cs +++ b/mcs/mcs/method.cs @@ -701,6 +701,10 @@ namespace Mono.CSharp { if (MemberType.IsStatic) { Error_StaticReturnType (); } + + if (MemberType.IsSpecialRuntimeType && Compiler.Settings.StdLib) { + Error_ReturnTypeCantBeRefAny (Location, ReturnType, Report); + } } public override void Emit () @@ -716,6 +720,8 @@ namespace Mono.CSharp { Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder); } else if (ReturnType.HasDynamicElement) { Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location); + } else if (ReturnType is ReadOnlyReferenceContainer) { + Module.PredefinedAttributes.IsReadOnly.EmitAttribute (CreateReturnBuilder ().Builder); } if (ReturnType.HasNamedTupleElement) { @@ -764,6 +770,11 @@ namespace Mono.CSharp { GetSignatureForError ()); } + public static void Error_ReturnTypeCantBeRefAny (Location loc, TypeSpec t, Report Report) + { + Report.Error (1599, loc, "The return type of `{0}' is not allowed", t.GetSignatureForError ()); + } + public bool IsPartialDefinition { get { return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null; @@ -1231,11 +1242,6 @@ namespace Mono.CSharp { "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?"); } - if (Compiler.Settings.StdLib && ReturnType.IsSpecialRuntimeType) { - Error1599 (Location, ReturnType, Report); - return false; - } - if (CurrentTypeParameters == null) { if (base_method != null && !IsExplicitImpl) { if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && MemberName.Name == "Equals") @@ -1261,8 +1267,9 @@ namespace Mono.CSharp { if ((ModFlags & Modifiers.ASYNC) != 0) { if (ReturnType.Kind != MemberKind.Void && ReturnType != Module.PredefinedTypes.Task.TypeSpec && - !ReturnType.IsGenericTask) { - Report.Error (1983, Location, "The return type of an async method must be void, Task, or Task"); + !ReturnType.IsGenericTask && + !ReturnType.IsCustomTaskType ()) { + Report.Error (1983, Location, "The return type of an async method must be void or task type"); } block = (ToplevelBlock) block.ConvertToAsyncTask (this, Parent.PartialContainer, parameters, ReturnType, null, Location); @@ -1396,11 +1403,6 @@ namespace Mono.CSharp { return base.EnableOverloadChecks (overload); } - public static void Error1599 (Location loc, TypeSpec t, Report Report) - { - Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", t.GetSignatureForError ()); - } - protected override bool ResolveMemberType () { if (CurrentTypeParameters != null) { @@ -2467,6 +2469,8 @@ namespace Mono.CSharp { Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder); } else if (ReturnType.HasDynamicElement) { Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location); + } else if (ReturnType is ReadOnlyReferenceContainer) { + Module.PredefinedAttributes.IsReadOnly.EmitAttribute (CreateReturnBuilder ().Builder); } if (ReturnType.HasNamedTupleElement) { diff --git a/mcs/mcs/modifiers.cs b/mcs/mcs/modifiers.cs index bfae5985a03..926ab5d1848 100644 --- a/mcs/mcs/modifiers.cs +++ b/mcs/mcs/modifiers.cs @@ -53,6 +53,7 @@ namespace Mono.CSharp DEBUGGER_HIDDEN = 0x400000, DEBUGGER_STEP_THROUGH = 0x800000, AutoProperty = 0x1000000, + REF = 0x2000000, AccessibilityMask = PUBLIC | PROTECTED | INTERNAL | PRIVATE, AllowedExplicitImplFlags = UNSAFE | EXTERN, diff --git a/mcs/mcs/module.cs b/mcs/mcs/module.cs index 00afac6c604..2293d825b36 100644 --- a/mcs/mcs/module.cs +++ b/mcs/mcs/module.cs @@ -265,6 +265,7 @@ namespace Mono.CSharp readonly Dictionary array_types; readonly Dictionary pointer_types; readonly Dictionary reference_types; + readonly Dictionary readonly_reference_types; readonly Dictionary attrs_cache; readonly Dictionary awaiters; readonly Dictionary type_info_cache; @@ -301,6 +302,7 @@ namespace Mono.CSharp array_types = new Dictionary (); pointer_types = new Dictionary (); reference_types = new Dictionary (); + readonly_reference_types = new Dictionary (); attrs_cache = new Dictionary (); awaiters = new Dictionary (); type_info_cache = new Dictionary (); @@ -427,6 +429,12 @@ namespace Mono.CSharp } } + internal Dictionary ReadonlyReferenceTypesCache { + get { + return readonly_reference_types; + } + } + internal Dictionary TypeInfoCache { get { return type_info_cache; diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs index 2bd2a498a91..cc10eee162b 100644 --- a/mcs/mcs/parameter.cs +++ b/mcs/mcs/parameter.cs @@ -1447,7 +1447,7 @@ namespace Mono.CSharp { expr = Child; - if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsGeneratedStructConstructor))) { + if (!(expr is Constant || expr is DefaultValueExpression || expr is DefaultLiteralExpression || (expr is New && ((New) expr).IsGeneratedStructConstructor))) { if (!(expr is ErrorExpression)) { rc.Report.Error (1736, Location, "The expression being assigned to optional parameter `{0}' must be a constant or default value", diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index 58ba2795e4b..9c51128548f 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -1160,7 +1160,8 @@ namespace Mono.CSharp { // if (ec.CurrentAnonymousMethod is AsyncInitializer) { var storey = (AsyncTaskStorey) ec.CurrentAnonymousMethod.Storey; - if (storey.ReturnType == ec.Module.PredefinedTypes.Task.TypeSpec) { + var s_return_type = storey.ReturnType; + if (s_return_type == ec.Module.PredefinedTypes.Task.TypeSpec) { // // Extra trick not to emit ret/leave inside awaiter body // @@ -1168,8 +1169,8 @@ namespace Mono.CSharp { return true; } - if (storey.ReturnType.IsGenericTask) - block_return_type = storey.ReturnType.TypeArguments[0]; + if (s_return_type.IsGenericTask || (s_return_type.Arity == 1 && s_return_type.IsCustomTaskType ())) + block_return_type = s_return_type.TypeArguments[0]; } if (ec.CurrentIterator != null) { @@ -1220,7 +1221,7 @@ namespace Mono.CSharp { return false; } - if (!async_type.IsGenericTask) { + if (!async_type.IsGeneric) { if (this is ContextualReturn) return true; @@ -2368,7 +2369,12 @@ namespace Mono.CSharp { if (initializer == null) return null; - var c = initializer as Constant; + Constant c; + if (initializer.Type == InternalType.DefaultType) + c = New.Constantify (li.Type, initializer.Location); + else + c = initializer as Constant; + if (c == null) { initializer.Error_ExpressionMustBeConstant (bc, initializer.Location, li.Name); return null; @@ -2407,14 +2413,14 @@ namespace Mono.CSharp { AddressTaken = 1 << 2, CompilerGenerated = 1 << 3, Constant = 1 << 4, - ForeachVariable = 1 << 5, - FixedVariable = 1 << 6, - UsingVariable = 1 << 7, + ForeachVariable = 1 << 5 | ReadonlyMask, + FixedVariable = 1 << 6 | ReadonlyMask, + UsingVariable = 1 << 7 | ReadonlyMask, IsLocked = 1 << 8, SymbolFileHidden = 1 << 9, ByRef = 1 << 10, - ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable + ReadonlyMask = 1 << 20 } TypeSpec type; @@ -2534,7 +2540,7 @@ namespace Mono.CSharp { public bool IsFixed { get { - return (flags & Flags.FixedVariable) != 0; + return (flags & Flags.FixedVariable) == Flags.FixedVariable; } set { flags = value ? flags | Flags.FixedVariable : flags & ~Flags.FixedVariable; @@ -2672,7 +2678,7 @@ namespace Mono.CSharp { public string GetReadOnlyContext () { - switch (flags & Flags.ReadonlyMask) { + switch (flags & (Flags.ForeachVariable | Flags.FixedVariable | Flags.UsingVariable)) { case Flags.FixedVariable: return "fixed variable"; case Flags.ForeachVariable: @@ -8191,7 +8197,9 @@ namespace Mono.CSharp { } if (iface_candidate == null) { - if (expr.Type != InternalType.ErrorType) { + if (expr.Type == InternalType.DefaultType) { + rc.Report.Error (8312, loc, "Use of default literal is not valid in this context"); + } else if (expr.Type != InternalType.ErrorType) { rc.Report.Error (1579, loc, "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `{1}' or is inaccessible", expr.Type.GetSignatureForError (), "GetEnumerator"); diff --git a/mcs/mcs/tuples.cs b/mcs/mcs/tuples.cs index bb7faf734df..901efdc9541 100644 --- a/mcs/mcs/tuples.cs +++ b/mcs/mcs/tuples.cs @@ -432,7 +432,7 @@ namespace Mono.CSharp { Expression source; List targetExprs; - List variablesToInfer; + List variables; Expression instance; public TupleDeconstruct (List targetExprs, Expression source, Location loc) @@ -442,10 +442,11 @@ namespace Mono.CSharp this.loc = loc; } - public TupleDeconstruct (List targetExprs, List variables, Expression source, Location loc) - : this (targetExprs, source, loc) + public TupleDeconstruct (List variables, Expression source, Location loc) { - this.variablesToInfer = variables; + this.source = source; + this.variables = variables; + this.loc = loc; } public override Expression CreateExpressionTree (ResolveContext ec) @@ -469,9 +470,18 @@ namespace Mono.CSharp var src_type = src.Type; if (src_type.IsTupleType) { - if (src_type.Arity != targetExprs.Count) { + int target_count; + + if (targetExprs == null) { + target_count = variables.Count; + targetExprs = new List (target_count); + } else { + target_count = targetExprs.Count; + } + + if (src_type.Arity != target_count) { rc.Report.Error (8132, loc, "Cannot deconstruct a tuple of `{0}' elements into `{1}' variables", - src_type.Arity.ToString (), targetExprs.Count.ToString ()); + src_type.Arity.ToString (CultureInfo.InvariantCulture), target_count.ToString (CultureInfo.InvariantCulture)); return null; } @@ -482,27 +492,44 @@ namespace Mono.CSharp instance = expr_variable.CreateReferenceExpression (rc, loc); } - for (int i = 0; i < targetExprs.Count; ++i) { + for (int i = 0; i < target_count; ++i) { var tle = src_type.TypeArguments [i]; - var lv = variablesToInfer? [i]; - if (lv != null) { - if (InternalType.HasNoType (tle)) { - rc.Report.Error (8130, Location, "Cannot infer the type of implicitly-typed deconstruction variable `{0}'", lv.Name); - lv.Type = InternalType.ErrorType; + if (variables != null) { + var variable = variables [i].Variable; + + if (variable.Type == InternalType.Discard) { + variables [i] = null; + targetExprs.Add (EmptyExpressionStatement.Instance); continue; } - lv.Type = tle; - lv.PrepareAssignmentAnalysis ((BlockContext) rc); - } + var variable_type = variables [i].TypeExpression; + + targetExprs.Add (new LocalVariableReference (variable, variable.Location)); + + if (variable_type is VarExpr) { + if (InternalType.HasNoType (tle)) { + rc.Report.Error (8130, Location, "Cannot infer the type of implicitly-typed deconstruction variable `{0}'", variable.Name); + tle = InternalType.ErrorType; + } + variable.Type = tle; + } else { + variable.Type = variable_type.ResolveAsType (rc); + } + + variable.PrepareAssignmentAnalysis ((BlockContext)rc); + } var element_src = tupleLiteral == null ? new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)) : tupleLiteral.Elements [i].Expr; targetExprs [i] = new SimpleAssign (targetExprs [i], element_src).Resolve (rc); } eclass = ExprClass.Value; + + // TODO: The type is same only if there is no target element conversion + // var res = (/*byte*/ b, /*short*/ s) = (2, 4); type = src.Type; return this; } @@ -527,11 +554,24 @@ namespace Mono.CSharp public override void Emit (EmitContext ec) { - throw new NotImplementedException (); + if (instance != null) + ((ExpressionStatement)source).EmitStatement (ec); + + foreach (ExpressionStatement expr in targetExprs) + expr.Emit (ec); + + var ctor = MemberCache.FindMember (type, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly) as MethodSpec; + ec.Emit (OpCodes.Newobj, ctor); } public override void EmitStatement (EmitContext ec) { + if (variables != null) { + foreach (var lv in variables) { + lv?.Variable.CreateBuilder (ec); + } + } + if (instance != null) ((ExpressionStatement) source).EmitStatement (ec); @@ -549,9 +589,6 @@ namespace Mono.CSharp if (leave_copy) throw new NotImplementedException (); - foreach (var lv in variablesToInfer) - lv.CreateBuilder (ec); - EmitStatement (ec); } @@ -563,11 +600,11 @@ namespace Mono.CSharp public void SetGeneratedFieldAssigned (FlowAnalysisContext fc) { - if (variablesToInfer == null) + if (variables == null) return; - foreach (var lv in variablesToInfer) - fc.SetVariableAssigned (lv.VariableInfo); + foreach (var lv in variables) + fc.SetVariableAssigned (lv.Variable.VariableInfo); } } } \ No newline at end of file diff --git a/mcs/mcs/typemanager.cs b/mcs/mcs/typemanager.cs index b6aff14e1c0..7a16cda2774 100644 --- a/mcs/mcs/typemanager.cs +++ b/mcs/mcs/typemanager.cs @@ -242,6 +242,7 @@ namespace Mono.CSharp // C# 7.0 public readonly PredefinedType[] Tuples; + public readonly PredefinedType SpanGeneric; public PredefinedTypes (ModuleContainer module) { @@ -301,6 +302,8 @@ namespace Mono.CSharp FormattableString = new PredefinedType (module, MemberKind.Class, "System", "FormattableString"); FormattableStringFactory = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "FormattableStringFactory"); + SpanGeneric = new PredefinedType (module, MemberKind.Struct, "System", "Span", 1); + // // Define types which are used for comparison. It does not matter // if they don't exist as no error report is needed @@ -348,6 +351,8 @@ namespace Mono.CSharp if (pt.Define ()) pt.TypeSpec.IsTupleType = true; } + + SpanGeneric.Define (); } } @@ -430,6 +435,7 @@ namespace Mono.CSharp ArrayEmpty = new PredefinedMember (module, types.Array, MemberFilter.Method ("Empty", 1, ParametersCompiled.EmptyReadOnlyParameters, null)); + // TODO: Must me static AsyncTaskMethodBuilderCreate = new PredefinedMember (module, types.AsyncTaskMethodBuilder, MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncTaskMethodBuilder.TypeSpec)); @@ -485,6 +491,7 @@ namespace Mono.CSharp AsyncTaskMethodBuilderTask = new PredefinedMember (module, types.AsyncTaskMethodBuilder, MemberFilter.Property ("Task", null)); + // TODO: Must me static AsyncTaskMethodBuilderGenericCreate = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); @@ -542,6 +549,7 @@ namespace Mono.CSharp AsyncTaskMethodBuilderGenericTask = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, MemberFilter.Property ("Task", null)); + // TODO: Must me static AsyncVoidMethodBuilderCreate = new PredefinedMember (module, types.AsyncVoidMethodBuilder, MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); @@ -1006,9 +1014,6 @@ namespace Mono.CSharp public T Resolve (Location loc) { - if (member != null) - return member; - if (Get () != null) return member; diff --git a/mcs/mcs/typespec.cs b/mcs/mcs/typespec.cs index d14e1ead3e3..a58a0fe5178 100644 --- a/mcs/mcs/typespec.cs +++ b/mcs/mcs/typespec.cs @@ -225,6 +225,8 @@ namespace Mono.CSharp } } + public bool IsByRefLike => (modifiers & Modifiers.REF) != 0; + // // Returns true for instances of System.Threading.Tasks.Task // @@ -1452,6 +1454,7 @@ namespace Mono.CSharp int TypeParametersCount { get; } TypeParameterSpec[] TypeParameters { get; } + TypeSpec GetAsyncMethodBuilder (); TypeSpec GetAttributeCoClass (); string GetAttributeDefaultMember (); AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa); @@ -1461,6 +1464,29 @@ namespace Mono.CSharp class InternalType : TypeSpec, ITypeDefinition { + sealed class InternalTypeAssembly : IAssemblyDefinition + { + public static readonly InternalTypeAssembly Instance = new InternalTypeAssembly (); + + public string FullName => throw new NotImplementedException (); + + public bool IsCLSCompliant => false; + + public bool IsMissing => false; + + public string Name => throw new NotImplementedException (); + + public byte [] GetPublicKeyToken () + { + throw new NotImplementedException (); + } + + public bool IsFriendAssemblyTo (IAssemblyDefinition assembly) + { + return false; + } + } + public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method"); public static readonly InternalType Arglist = new InternalType ("__arglist"); public static readonly InternalType MethodGroup = new InternalType ("method group"); @@ -1470,6 +1496,8 @@ namespace Mono.CSharp public static readonly InternalType ErrorType = new InternalType (""); public static readonly InternalType VarOutType = new InternalType ("var out"); public static readonly InternalType ThrowExpr = new InternalType ("throw expression"); + public static readonly InternalType DefaultType = new InternalType ("default"); + public static readonly InternalType Discard = new InternalType ("discard"); readonly string name; @@ -1494,7 +1522,7 @@ namespace Mono.CSharp IAssemblyDefinition ITypeDefinition.DeclaringAssembly { get { - throw new NotImplementedException (); + return InternalTypeAssembly.Instance; } } @@ -1561,6 +1589,11 @@ namespace Mono.CSharp #region ITypeDefinition Members + TypeSpec ITypeDefinition.GetAsyncMethodBuilder () + { + return null; + } + TypeSpec ITypeDefinition.GetAttributeCoClass () { return null; @@ -1614,7 +1647,7 @@ namespace Mono.CSharp public static bool HasNoType (TypeSpec type) { - return type == AnonymousMethod || type == MethodGroup || type == NullLiteral || type == ThrowExpr; + return type == AnonymousMethod || type == MethodGroup || type == NullLiteral || type == ThrowExpr || type == DefaultType; } } @@ -1749,6 +1782,11 @@ namespace Mono.CSharp } } + public TypeSpec GetAsyncMethodBuilder () + { + return null; + } + public TypeSpec GetAttributeCoClass () { return Element.MemberDefinition.GetAttributeCoClass (); @@ -1996,9 +2034,10 @@ namespace Mono.CSharp [System.Diagnostics.DebuggerDisplay("{DisplayDebugInfo()}")] class ReferenceContainer : ElementTypeSpec { - ReferenceContainer (TypeSpec element) + protected ReferenceContainer (TypeSpec element) : base (MemberKind.ByRef, element, null) { + cache = null; } public override IList Interfaces { @@ -2039,6 +2078,39 @@ namespace Mono.CSharp return pc; } + + protected override void InitializeMemberCache(bool onlyTypes) + { + cache = Element.MemberCache; + } + } + + [System.Diagnostics.DebuggerDisplay ("{DisplayDebugInfo()}")] + class ReadOnlyReferenceContainer : ReferenceContainer + { + public ReadOnlyReferenceContainer (TypeSpec element) + : base (element) + { + } + + string DisplayDebugInfo () + { + return "ref readonly " + GetSignatureForError (); + } + + public new static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element) + { + if (element.Kind == MemberKind.ByRef) + throw new ArgumentException (); + + ReadOnlyReferenceContainer pc; + if (!module.ReadonlyReferenceTypesCache.TryGetValue (element, out pc)) { + pc = new ReadOnlyReferenceContainer (element); + module.ReadonlyReferenceTypesCache.Add (element, pc); + } + + return pc; + } } class PointerContainer : ElementTypeSpec diff --git a/mcs/tests/gtest-409.cs b/mcs/tests/gtest-409.cs index 8db59d7e48d..606ae3685d1 100644 --- a/mcs/tests/gtest-409.cs +++ b/mcs/tests/gtest-409.cs @@ -1,3 +1,4 @@ +// Compiler options: -langversion:latest using System; // @@ -175,6 +176,11 @@ public class ConditionalParsing var x = args ?.2f : -.2f; } + void Test_23 (string args) + { + var x = args == null ? default : 1; + } + static void Helper (T arg) { } diff --git a/mcs/tests/test-948.cs b/mcs/tests/test-948.cs new file mode 100644 index 00000000000..34b3ab9a0c4 --- /dev/null +++ b/mcs/tests/test-948.cs @@ -0,0 +1,16 @@ +// Compiler options: -langversion:7.2 -unsafe + +using System; + +class X +{ + public static void Main () + { + Span stackSpan = stackalloc int[100]; + } + + unsafe void Foo () + { + + } +} \ No newline at end of file diff --git a/mcs/tests/test-async-94.cs b/mcs/tests/test-async-94.cs new file mode 100644 index 00000000000..ce9a30409bb --- /dev/null +++ b/mcs/tests/test-async-94.cs @@ -0,0 +1,127 @@ +using System; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; + +[AsyncMethodBuilder (typeof(MyTaskMethodBuilder<>))] +class MyTask +{ +} + +[AsyncMethodBuilder (typeof(MyTaskMethodBuilder))] +class MyTask +{ +} + +class MyTaskMethodBuilder +{ + public static MyTaskMethodBuilder Create() + { + return null; + } + + public MyTask Task { + get { + return null; + } + } + + public void SetException (Exception exception) + { + + } + + public void SetResult () + { + + } + + public void AwaitOnCompleted (ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine + { + + } + + public void AwaitUnsafeOnCompleted (ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine + { + + } + + public void Start (ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine + { + + } + + public void SetStateMachine (IAsyncStateMachine stateMachine) + { + + } +} + +class MyTaskMethodBuilder +{ + public static MyTaskMethodBuilder Create() + { + return null; + } + + public MyTask Task { + get { + return null; + } + } + + public void SetException (Exception exception) + { + + } + + public void SetResult (T result) + { + + } + + public void AwaitOnCompleted (ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine + { + + } + + public void AwaitUnsafeOnCompleted (ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine + { + + } + + public void Start (ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine + { + + } + + public void SetStateMachine (IAsyncStateMachine stateMachine) + { + + } +} + +class X +{ + public async MyTask Test () + { + await Task.Delay (1); + } + + public async MyTask Test2 () + { + await Task.Delay (1); + return 2; + } + + public async ValueTask Test3 () + { + await Task.Delay (1); + return "as"; + } + + public static void Main () + { + var x = new X (); + var r1 = x.Test3 ().Result; + } +} \ No newline at end of file diff --git a/mcs/tests/test-default-01.cs b/mcs/tests/test-default-01.cs new file mode 100644 index 00000000000..823e33c451b --- /dev/null +++ b/mcs/tests/test-default-01.cs @@ -0,0 +1,52 @@ +// Compiler options: -langversion:latest + +static class X +{ + const int c1 = default; + const int c2 = default (int); + + public static void Main () + { + int a = default; + var b = (int) default; + const int c = default; + var d = new[] { 1, default }; + dynamic e = default; + int f = checked (default); + (int a, int b) g = (1, default); + var h = 1 != default; + var i = default == M4 (); + } + + static int M1 () + { + return default; + } + + static void M2 () + { + try { + throw new System.Exception (); + } catch (System.Exception) when (default) { + } + + if (default) { + } + } + + static void M3 (int x = default) + { + } + + static System.Func M4 () + { + return () => default; + } +} +/* +enum E +{ + A = default, + B = default + 1 +} +*/ \ No newline at end of file diff --git a/mcs/tests/test-default-02.cs b/mcs/tests/test-default-02.cs new file mode 100644 index 00000000000..0039782e5f2 --- /dev/null +++ b/mcs/tests/test-default-02.cs @@ -0,0 +1,33 @@ +// Compiler options: -langversion:latest + +class C +{ + static void Main() + { + M (default, 1); + + M2 (default); + M2 (null); + + var res = Test (default); + } + + + static void M (T x, T y) + { + } + + static void M2 (params object[] x) + { + } + + static byte[] Test (S x) + { + return null; + } +} + +struct S +{ + +} \ No newline at end of file diff --git a/mcs/tests/test-discards-01.cs b/mcs/tests/test-discards-01.cs new file mode 100644 index 00000000000..54cf29779c6 --- /dev/null +++ b/mcs/tests/test-discards-01.cs @@ -0,0 +1,36 @@ +using System; + +class X +{ + public static void Main () + { + string s = null; + + _ = 1; + { + char _ = '4'; + } + + _ = TestValue (); + + _ = _ = s; + + byte k1; + var s1 = (k1, _) = (1, s); + + Func l1 = () => _ = (_, _) = (1, s); + + TryGetValue (out _); + } + + static bool TryGetValue (out int arg) + { + arg = 3; + return true; + } + + static int TestValue () + { + return 4; + } +} \ No newline at end of file diff --git a/mcs/tests/test-named-11.cs b/mcs/tests/test-named-11.cs new file mode 100644 index 00000000000..a01d2883b9c --- /dev/null +++ b/mcs/tests/test-named-11.cs @@ -0,0 +1,13 @@ +// Compiler options: -langversion:7.2 + +class X +{ + public static void Main () + { + Test (arg: 1, ""); + } + + static void Test (int arg, string str) + { + } +} \ No newline at end of file diff --git a/mcs/tests/test-readonly-02.cs b/mcs/tests/test-readonly-02.cs new file mode 100644 index 00000000000..231b8cd8fda --- /dev/null +++ b/mcs/tests/test-readonly-02.cs @@ -0,0 +1,27 @@ +// Compiler options: -langversion:latest +using System; + +public delegate ref readonly int D (int x); + +class X +{ + public static void Main () + { + + } + + Guid g; + + ref readonly Guid TestMethod () + { + return ref g; + } + + ref readonly Guid TestProp { + get { + ref readonly var rg = ref g; + return ref rg; + } + } + +} \ No newline at end of file diff --git a/mcs/tests/test-readonly-03.cs b/mcs/tests/test-readonly-03.cs new file mode 100644 index 00000000000..14cb958b41a --- /dev/null +++ b/mcs/tests/test-readonly-03.cs @@ -0,0 +1,16 @@ +// Compiler options: -langversion:latest +using System; + +readonly struct S +{ + static S shared = new S (); + + public S (int arg) + { + this = shared; + } + + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/test-ref-07.cs b/mcs/tests/test-ref-07.cs new file mode 100644 index 00000000000..4aa16579752 --- /dev/null +++ b/mcs/tests/test-ref-07.cs @@ -0,0 +1,30 @@ +// Compiler options: -langversion:latest + +public readonly partial ref struct Test +{ + public static void Main () + { + var m = new Test (); + m.Method (); + } + + Test Method () + { + return new Test (); + } +} + +ref struct Second +{ + Test field; +} + +public abstract class P +{ + public abstract Test Span { get; } +} + +public interface II +{ + Test Span { get; } +} diff --git a/mcs/tests/test-ref-08.cs b/mcs/tests/test-ref-08.cs new file mode 100644 index 00000000000..f4ff50f4c5c --- /dev/null +++ b/mcs/tests/test-ref-08.cs @@ -0,0 +1,101 @@ +using System; + +namespace ClassLibrary1 +{ + public class C + { + + class B + { + int v; + public ref int this[int index] + { + get + { + return ref v; + } + } + } + + + class Gen where T : struct + { + T v; + public ref T this[int index] + { + get + { + return ref v; + } + } + } + + struct Val + { + } + + class BB + { + Val v; + public ref Val this[int index] + { + get + { + return ref v; + } + } + } + + void MM () + { + var bbb = new BB(); + Val v1 = bbb[0]; + bbb[1] = v1; + + ref Val v2 = ref bbb[2]; + bbb[2] = v2; + } + + static int[] a = new int[1]; + public static void Main() + { + var bb = new B(); + int b = 1; + bb[0] = b; + a[0] = Add2(ref b, 2); + + var bbb = new BB(); + bbb[0] = new Val(); + + var v = new Val(); + bbb[1] = v; + + var v2 = bbb[2]; + + bbb[3] = v2; + + + bbb[3] = bbb[2]; + + + + var ggg = new Gen(); + ggg[0] = new Val(); + + var g = new Val(); + ggg[1] = v; + + var g2 = ggg[2]; + + ggg[3] = v2; + + + ggg[3] = ggg[2]; + } + + public static ref int Add2(ref int a, int b) + { + return ref a; + } + } +} \ No newline at end of file diff --git a/mcs/tests/test-ref-09.cs b/mcs/tests/test-ref-09.cs new file mode 100644 index 00000000000..5d0e89e5c1a --- /dev/null +++ b/mcs/tests/test-ref-09.cs @@ -0,0 +1,12 @@ +struct rigidbody { public float x; } + +class Program +{ + static rigidbody a; + static ref rigidbody property_returning_struct_by_ref => ref a; + + static void Main() + { + System.Console.WriteLine (property_returning_struct_by_ref.x); + } +} \ No newline at end of file diff --git a/mcs/tests/test-ref-10.cs b/mcs/tests/test-ref-10.cs new file mode 100644 index 00000000000..88e201d3174 --- /dev/null +++ b/mcs/tests/test-ref-10.cs @@ -0,0 +1,24 @@ +// Compiler options: -langversion:latest + +using System; + +ref struct ValueStringBuilder +{ + public override string ToString () + { + return "aaa"; + } +} + + +class X +{ + public static int Main () + { + var s = new ValueStringBuilder (); + if (s.ToString () != "aaa") + return 1; + + return 0; + } +} \ No newline at end of file diff --git a/mcs/tests/test-tuple-07.cs b/mcs/tests/test-tuple-07.cs new file mode 100644 index 00000000000..cc7ce5837ce --- /dev/null +++ b/mcs/tests/test-tuple-07.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +// Parser tests + +class ParserTest +{ + IEnumerable<(Object vertex, int distance)> Test () + { + return null; + } + + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/test-tuple-09.cs b/mcs/tests/test-tuple-09.cs new file mode 100644 index 00000000000..3f15cae6cf1 --- /dev/null +++ b/mcs/tests/test-tuple-09.cs @@ -0,0 +1,19 @@ +using System; + +class TupleDeconstructionDeclaration +{ + public static int Main () + { + (string s, long l) = GetValues (); + (var vs, var vl) = GetValues (); + (object o, var vl2) = GetValues (); + (string ds, _) = GetValues (); + + return 0; + } + + static (string, long) GetValues () + { + return ("a", 3); + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_x.xml b/mcs/tests/ver-il-net_4_x.xml index c2c98123305..4dbc7042a8a 100644 --- a/mcs/tests/ver-il-net_4_x.xml +++ b/mcs/tests/ver-il-net_4_x.xml @@ -14659,6 +14659,9 @@ 24 + + 16 + @@ -52808,6 +52811,19 @@ + + + + 16 + + + 2 + + + 7 + + + @@ -66893,6 +66909,117 @@ + + + + 7 + + + + + 7 + + + + + 10 + + + 10 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 7 + + + + + 10 + + + 10 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 7 + + + + + 33 + + + 33 + + + 33 + + + 23 + + + 7 + + + + + 157 + + + 13 + + + + + 165 + + + 13 + + + + + 169 + + + 13 + + + @@ -68527,6 +68654,47 @@ + + + + 53 + + + 10 + + + 31 + + + 2 + + + 38 + + + 9 + + + + + + + 36 + + + 2 + + + 2 + + + 7 + + + 10 + + + @@ -68610,6 +68778,30 @@ + + + + 63 + + + 13 + + + 10 + + + 7 + + + + + 25 + + + 7 + + + @@ -70689,6 +70881,19 @@ + + + + 13 + + + 2 + + + 7 + + + @@ -72778,6 +72983,49 @@ + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 2 + + + 15 + + + 17 + + + 7 + + + + + + + 2 + + + 13 + + + 15 + + + @@ -72906,6 +73154,95 @@ + + + + 18 + + + 18 + + + + + 0 + + + 7 + + + + + + + 60 + + + 245 + + + 10 + + + 7 + + + 12 + + + + + 15 + + + 7 + + + + + 15 + + + 7 + + + + + 15 + + + 7 + + + + + + + 13 + + + 17 + + + 7 + + + + + + + 14 + + + + + 47 + + + 7 + + + @@ -73374,6 +73711,56 @@ + + + + 10 + + + 2 + + + 7 + + + + + + + 19 + + + 41 + + + 21 + + + 7 + + + + + 212 + + + 13 + + + + + + + 99 + + + 21 + + + 7 + + +