--- /dev/null
+// CS0106: The modifier `readonly' is not valid for this item
+// Line: 6
+// Compiler option: -langversion:latest
+
+readonly interface I
+{
+}
--- /dev/null
+// CS0459: Cannot take the address of `this' because it is read-only
+// Line: 11
+// Compiler options: -unsafe -langversion:latest
+
+readonly struct X
+{
+ unsafe void Test ()
+ {
+ fixed (X* x = &this) {
+
+ }
+ }
+}
--- /dev/null
+// CS1604: Cannot assign to `this' because it is read-only
+// Line: 8
+// Compiler options: -langversion:latest
+
+readonly struct S
+{
+ void Foo ()
+ {
+ this = new S ();
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1605: Cannot pass `this' as a ref or out argument because it is read-only
+// Line: 14
+// Compiler options: -langversion:latest
+
+readonly struct X
+{
+ void Test (out X x)
+ {
+ x = new X ();
+ }
+
+ void Run ()
+ {
+ Test (out this);
+ }
+}
--- /dev/null
+// CS1644: Feature `readonly structs' cannot be used because it is not part of the C# 7.0 language specification
+// Line: 5
+// Compiler options: -langversion:7
+
+readonly struct S
+{
+}
\ No newline at end of file
-// CS8145: Auto-implemented properties cannot return by reference
+// CS8145: Auto-implemented property `X.TestProp' cannot return by reference
// Line: 6
public class X
--- /dev/null
+// CS8340: `S.field': Instance fields in readonly structs must be readonly
+// Line: 6
+// Compiler options: -langversion:latest
+
+readonly partial struct S
+{
+
+}
+
+partial struct S
+{
+ int field;
+}
\ No newline at end of file
--- /dev/null
+// CS8340: `S.field': Instance fields in readonly structs must be readonly
+// Line: 6
+// Compiler options: -langversion:latest
+
+readonly struct S
+{
+ int field;
+}
\ No newline at end of file
--- /dev/null
+// CS8341: Auto-implemented instance property `S.field' in readonly structs must be readonly
+// Line: 6
+// Compiler options: -langversion:latest
+
+readonly struct S
+{
+ int field { get; set; }
+}
\ No newline at end of file
--- /dev/null
+// CS8342: `S.e': Field-like instance events are not allowed in readonly structs
+// Line: 6
+// Compiler options: -langversion:latest
+
+using System;
+
+readonly struct S
+{
+ event Action e;
+}
\ No newline at end of file
// New in .NET 4.7
public readonly PredefinedTupleElementNamesAttribute TupleElementNames;
+ // New in .NET 4.7.1
+ public readonly PredefinedAttribute IsReadOnly;
+
//
// Optional types which are used as types and for member lookup
//
CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
TupleElementNames = new PredefinedTupleElementNamesAttribute (module, "System.Runtime.CompilerServices", "TupleElementNamesAttribute");
+ IsReadOnly = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IsReadOnlyAttribute");
// TODO: Should define only attributes which are used for comparison
const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.UNSAFE |
- Modifiers.PRIVATE;
+ Modifiers.PRIVATE |
+ Modifiers.READONLY;
public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
: base (parent, name, attrs, MemberKind.Struct)
public override void Emit ()
{
+ if ((ModFlags & Modifiers.READONLY) != 0)
+ Module.PredefinedAttributes.IsReadOnly.EmitAttribute (TypeBuilder);
+
CheckStructCycles ();
base.Emit ();
opt_modifiers
opt_partial
STRUCT
- {
- }
type_declaration_name
- {
+ {
+ var mods = (Modifiers) $2;
+ if ((mods & Modifiers.READONLY) != 0 && lang_version < LanguageVersion.V_7_2) {
+ FeatureIsNotAvailable (GetLocation ($4), "readonly structs");
+ }
+
lexer.ConstraintsParsing = true;
valid_param_mod = ParameterModifierType.PrimaryConstructor;
- push_current_container (new Struct (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3);
+ push_current_container (new Struct (current_container, (MemberName) $5, mods, (Attributes) $1), $3);
}
opt_primary_parameters
opt_class_base
valid_param_mod = 0;
lexer.ConstraintsParsing = false;
- if ($8 != null)
- current_type.PrimaryConstructorParameters = (ParametersCompiled) $8;
+ if ($7 != null)
+ current_type.PrimaryConstructorParameters = (ParametersCompiled) $7;
- if ($10 != null)
- current_container.SetConstraints ((List<Constraints>) $10);
+ if ($9 != null)
+ current_container.SetConstraints ((List<Constraints>) $9);
if (doc_support)
current_container.PartialContainer.DocComment = Lexer.consume_doc_comment ();
}
opt_semicolon
{
- if ($16 == null) {
- lbag.AppendToMember (current_container, GetLocation ($12), GetLocation ($15));
+ if ($15 == null) {
+ lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($14));
} else {
- lbag.AppendToMember (current_container, GetLocation ($12), GetLocation ($15), GetLocation ($17));
+ lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($14), GetLocation ($16));
}
$$ = pop_current_class ();
}
if (eclass == ExprClass.Unresolved)
ResolveBase (ec);
- if (type.IsClass){
+ if (type.IsClass || type.IsReadOnly) {
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)
return true;
}
+ protected override void DoMemberTypeIndependentChecks ()
+ {
+ if ((Parent.PartialContainer.ModFlags & Modifiers.READONLY) != 0 && (ModFlags & (Modifiers.READONLY | Modifiers.STATIC)) == 0) {
+ Report.Error (8340, Location, "`{0}': Instance fields in readonly structs must be readonly",
+ GetSignatureForError ());
+ }
+
+ base.DoMemberTypeIndependentChecks ();
+ }
+
protected override void DoMemberTypeDependentChecks ()
{
if ((ModFlags & Modifiers.BACKING_FIELD) != 0)
}
}
- if (kind == MemberKind.Class) {
+ switch (kind) {
+ case MemberKind.Class:
if ((ma & TypeAttributes.Sealed) != 0) {
if ((ma & TypeAttributes.Abstract) != 0)
mod |= Modifiers.STATIC;
} else if ((ma & TypeAttributes.Abstract) != 0) {
mod |= Modifiers.ABSTRACT;
}
+ break;
+ case MemberKind.Struct:
+ if (HasAttribute (CustomAttributeData.GetCustomAttributes (type), "IsReadOnlyAttribute", CompilerServicesNamespace)) {
+ mod |= Modifiers.READONLY;
+ }
+
+ break;
}
}
}
if (MemberType.Kind == MemberKind.ByRef) {
- Report.Error (8145, Location, "Auto-implemented properties cannot return by reference");
+ Report.Error (8145, Location, "Auto-implemented property `{0}' cannot return by reference",
+ GetSignatureForError ());
return false;
}
+ if ((Parent.PartialContainer.ModFlags & Modifiers.READONLY) != 0 && Set != null && !IsStatic) {
+ Report.Error (8341, Location, "Auto-implemented instance property `{0}' in readonly structs must be readonly",
+ GetSignatureForError ());
+ }
+
if (Compiler.Settings.Version < LanguageVersion.V_3 && Initializer == null)
Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented properties");
base.ApplyAttributeBuilder (a, ctor, cdata, pa);
}
+ protected override void DoMemberTypeIndependentChecks ()
+ {
+ if ((Parent.PartialContainer.ModFlags & Modifiers.READONLY) != 0 && (ModFlags & Modifiers.STATIC) == 0) {
+ Report.Error (8342, Location, "`{0}': Field-like instance events are not allowed in readonly structs",
+ GetSignatureForError ());
+ }
+
+ base.DoMemberTypeIndependentChecks ();
+ }
+
public override bool Define()
{
var mod_flags_src = ModFlags;
}
}
+ public bool IsReadOnly => (modifiers & Modifiers.READONLY) != 0;
+
//
// Returns true for instances of any System.ValueTuple<......> type
//
--- /dev/null
+// Compiler options: -langversion:latest
+
+using System;
+
+readonly struct S
+{
+ readonly int field;
+
+ static int sf;
+ static event Action e;
+ static int Prop { get; set; }
+
+ public static void Main ()
+ {
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="test-readonly-01.cs">
+ <type name="S">
+ <method name="Void add_e(System.Action)" attrs="2193">
+ <size>40</size>
+ </method>
+ <method name="Void remove_e(System.Action)" attrs="2193">
+ <size>40</size>
+ </method>
+ <method name="Int32 get_Prop()" attrs="2193">
+ <size>13</size>
+ </method>
+ <method name="Void set_Prop(Int32)" attrs="2193">
+ <size>7</size>
+ </method>
+ <method name="Void Main()" attrs="150">
+ <size>2</size>
+ </method>
+ </type>
+ </test>
<test name="test-ref-01.cs">
<type name="X">
<method name="Void Main()" attrs="150">