diff options
author | Marek Safar <marek.safar@gmail.com> | 2017-10-25 17:40:21 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2017-11-21 11:15:00 +0300 |
commit | 2c160ed9a7d88410b3dfb21d5c83ca8a04eac766 (patch) | |
tree | d708f8636a5634975843b5c7d6b9f2765df83fd5 | |
parent | 73bd521c075b30bcbf349bdb7381d3b6b9fc3c69 (diff) |
[mcs] C# 7.2 ref struct feature
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"> |