Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Safar <marek.safar@gmail.com>2017-10-25 17:40:21 +0300
committerMarek Safar <marek.safar@gmail.com>2017-11-21 11:15:00 +0300
commit2c160ed9a7d88410b3dfb21d5c83ca8a04eac766 (patch)
treed708f8636a5634975843b5c7d6b9f2765df83fd5
parent73bd521c075b30bcbf349bdb7381d3b6b9fc3c69 (diff)
[mcs] C# 7.2 ref struct feature
-rw-r--r--mcs/errors/cs0029-39.cs15
-rw-r--r--mcs/errors/cs0029-40.cs19
-rw-r--r--mcs/errors/cs0029-41.cs12
-rw-r--r--mcs/errors/cs0030-17.cs15
-rw-r--r--mcs/errors/cs0123-10.cs18
-rw-r--r--mcs/errors/cs0123-11.cs12
-rw-r--r--mcs/errors/cs0306-4.cs15
-rw-r--r--mcs/errors/cs0611-3.cs15
-rw-r--r--mcs/errors/cs1599-2.cs2
-rw-r--r--mcs/errors/cs1599-3.cs2
-rw-r--r--mcs/errors/cs1599-4.cs12
-rw-r--r--mcs/errors/cs1599.cs2
-rw-r--r--mcs/errors/cs1644-57.cs7
-rw-r--r--mcs/errors/cs4012-3.cs19
-rw-r--r--mcs/errors/cs8175-2.cs19
-rw-r--r--mcs/errors/cs8343.cs12
-rw-r--r--mcs/errors/cs8345-2.cs12
-rw-r--r--mcs/errors/cs8345.cs12
-rw-r--r--mcs/mcs/attribute.cs2
-rw-r--r--mcs/mcs/class.cs25
-rw-r--r--mcs/mcs/convert.cs5
-rw-r--r--mcs/mcs/cs-parser.jay23
-rw-r--r--mcs/mcs/cs-tokenizer.cs16
-rw-r--r--mcs/mcs/delegate.cs12
-rw-r--r--mcs/mcs/ecore.cs7
-rw-r--r--mcs/mcs/expression.cs14
-rw-r--r--mcs/mcs/generic.cs4
-rw-r--r--mcs/mcs/import.cs4
-rw-r--r--mcs/mcs/method.cs19
-rw-r--r--mcs/mcs/modifiers.cs1
-rw-r--r--mcs/mcs/typespec.cs2
-rw-r--r--mcs/tests/test-ref-07.cs30
-rw-r--r--mcs/tests/ver-il-net_4_x.xml18
33 files changed, 370 insertions, 32 deletions
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/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/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<string>()' parameters
+// Line: 16
+// Compiler options: -langversion:latest
+
+using System;
+
+public ref struct S
+{
+}
+
+class Test
+{
+ public static void Main ()
+ {
+ var s = new S ();
+ Func<string> 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<string>()' parameters
+// Line: 16
+
+using System;
+
+class Test
+{
+ public static void Main ()
+ {
+ Func<string> f = default (TypedReference).ToString;
+ }
+} \ No newline at end of file
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<T>
+{
+ public static void Foo ()
+ {
+ Test<S> 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/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/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/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/mcs/attribute.cs b/mcs/mcs/attribute.cs
index 3ff2d68ccb5..4f520b7487e 100644
--- a/mcs/mcs/attribute.cs
+++ b/mcs/mcs/attribute.cs
@@ -1757,6 +1757,7 @@ namespace Mono.CSharp {
// 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
@@ -1839,6 +1840,7 @@ namespace Mono.CSharp {
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 cdf571a031d..3fd615907d5 100644
--- a/mcs/mcs/class.cs
+++ b/mcs/mcs/class.cs
@@ -3041,7 +3041,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)
@@ -3157,6 +3158,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 ();
@@ -3231,6 +3235,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;
}
@@ -3933,7 +3941,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",
@@ -3942,6 +3950,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/convert.cs b/mcs/mcs/convert.cs
index b11477c1043..46989cd2757 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:
@@ -1967,7 +1970,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..db7e06b2f8c 100644
--- a/mcs/mcs/cs-parser.jay
+++ b/mcs/mcs/cs-parser.jay
@@ -336,6 +336,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
@@ -1015,17 +1016,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 +1089,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);
}
@@ -8334,6 +8352,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 fd5659d22fc..97fcbc70ee3 100644
--- a/mcs/mcs/cs-tokenizer.cs
+++ b/mcs/mcs/cs-tokenizer.cs
@@ -812,10 +812,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 ();
@@ -904,6 +906,12 @@ namespace Mono.CSharp
}
break;
+ case Token.REF:
+ if (peek_token () == Token.STRUCT) {
+ token ();
+ res = Token.REF_STRUCT;
+ }
+ break;
}
diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs
index 80eb7e265f1..f3772e7cd8b 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;
}
@@ -603,8 +603,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/ecore.cs b/mcs/mcs/ecore.cs
index 85381113e48..20484fe6e9f 100644
--- a/mcs/mcs/ecore.cs
+++ b/mcs/mcs/ecore.cs
@@ -4177,6 +4177,13 @@ 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) {
+ // 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 ());
+ }
}
}
diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs
index 01c3a1ca0a6..7e7dbfd2981 100644
--- a/mcs/mcs/expression.cs
+++ b/mcs/mcs/expression.cs
@@ -6744,10 +6744,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) {
@@ -11607,7 +11611,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);
diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs
index 625cd0c773f..6bc036581f6 100644
--- a/mcs/mcs/generic.cs
+++ b/mcs/mcs/generic.cs
@@ -2292,7 +2292,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 +3102,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;
diff --git a/mcs/mcs/import.cs b/mcs/mcs/import.cs
index 1cddf7c01f4..81cb469171a 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;
}
}
diff --git a/mcs/mcs/method.cs b/mcs/mcs/method.cs
index ccd4898e91c..7b9bc5b5818 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 ()
@@ -764,6 +768,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 +1240,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")
@@ -1396,11 +1400,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) {
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/typespec.cs b/mcs/mcs/typespec.cs
index d14e1ead3e3..a3b9505bf06 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<T>
//
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/ver-il-net_4_x.xml b/mcs/tests/ver-il-net_4_x.xml
index d4d18e5def7..93672cf9e9f 100644
--- a/mcs/tests/ver-il-net_4_x.xml
+++ b/mcs/tests/ver-il-net_4_x.xml
@@ -72906,6 +72906,24 @@
</method>
</type>
</test>
+ <test name="test-ref-07.cs">
+ <type name="Test">
+ <method name="Void Main()" attrs="150">
+ <size>18</size>
+ </method>
+ <method name="Test Method()" attrs="129">
+ <size>18</size>
+ </method>
+ </type>
+ <type name="P">
+ <method name="Test get_Span()" attrs="3526">
+ <size>0</size>
+ </method>
+ <method name="Void .ctor()" attrs="6276">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-ref-08.cs">
<type name="ClassLibrary1.C">
<method name="Void MM()" attrs="129">