diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index cef0c023a..8cbb8a1ff 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -191,7 +191,7 @@ namespace ICSharpCode.Decompiler.IL
declaringType = new ParameterizedType(declaringType, declaringType.TypeParameters);
}
ILVariable ilVar = CreateILVariable(-1, declaringType, "this");
- ilVar.IsRefReadOnly = declaringType.GetDefinition()?.IsReadOnly == true;
+ ilVar.IsRefReadOnly = method.ThisIsRefReadOnly;
parameterVariables[paramIndex++] = ilVar;
}
while (paramIndex < parameterVariables.Length) {
diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
index c1a5de160..840c77e9b 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
@@ -272,8 +272,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var type = method.DeclaringType;
if (type.IsReferenceType == true)
return false; // reference types are never implicitly copied
- if (type.GetDefinition()?.IsReadOnly == true)
- return false; // readonly structs are never implicitly copied
+ if (method.ThisIsRefReadOnly)
+ return false; // no copies for calls on readonly structs
return true;
}
diff --git a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs
index c53d1cc60..1c98eb476 100644
--- a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs
@@ -40,6 +40,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
///
bool ReturnTypeIsRefReadOnly { get; }
+ ///
+ /// Gets whether the method is readonly (C# 8): accepts the 'this' reference as ref readonly
+ ///
+ bool ThisIsRefReadOnly { get; }
+
///
/// Gets the type parameters of this method; or an empty list if the method is not generic.
///
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
index 02d439f84..2a11babee 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
@@ -133,6 +133,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IEnumerable IMethod.GetReturnTypeAttributes() => EmptyList.Instance;
bool IMethod.ReturnTypeIsRefReadOnly => false;
+ bool IMethod.ThisIsRefReadOnly => false;
public IReadOnlyList TypeParameters { get; set; } = EmptyList.Instance;
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs
index 6a42b4364..cb53d51a6 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs
@@ -117,6 +117,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IEnumerable IEntity.GetAttributes() => baseMethod.GetAttributes();
IEnumerable IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes();
bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly;
+ bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly;
///
/// We consider local functions as always static, because they do not have a "this parameter".
/// Even local functions in instance methods capture this.
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
index d97382984..57e096823 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
@@ -426,6 +426,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
#endregion
+ public bool ThisIsRefReadOnly => DeclaringTypeDefinition?.IsReadOnly ?? false;
+
public Accessibility Accessibility => GetAccessibility(attributes);
internal static Accessibility GetAccessibility(MethodAttributes attr)
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs
index 311395fc4..c25ba6013 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs
@@ -97,6 +97,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable GetReturnTypeAttributes() => methodDefinition.GetReturnTypeAttributes();
public bool ReturnTypeIsRefReadOnly => methodDefinition.ReturnTypeIsRefReadOnly;
+ bool IMethod.ThisIsRefReadOnly => methodDefinition.ThisIsRefReadOnly;
+
public IReadOnlyList TypeParameters {
get {
return specializedTypeParameters ?? methodDefinition.TypeParameters;
diff --git a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs
index a151d1464..ecc0cbf22 100644
--- a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs
@@ -114,6 +114,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
IEnumerable IEntity.GetAttributes() => baseMethod.GetAttributes();
IEnumerable IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes();
bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly;
+ bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly;
public IReadOnlyList TypeParameters {
get { return baseMethod.TypeParameters; }