diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
index aa0025e273baa..f65c304f4a702 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
@@ -14,6 +14,7 @@
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.PooledObjects;
+using Microsoft.CodeAnalysis.Symbols;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
@@ -1606,6 +1607,26 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
ref attributes,
compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor));
}
+
+ // Add MetadataUpdateOriginalTypeAttribute when a reloadable type is emitted to EnC delta
+ if (moduleBuilder.EncSymbolChanges?.IsReplaced(((ISymbolInternal)this).GetISymbol()) == true)
+ {
+ // Note that we use this source named type symbol in the attribute argument (of System.Type).
+ // We do not have access to the original symbol from this compilation. However, System.Type
+ // is encoded in the attribute as a string containing a fully qualified type name.
+ // The name of the current type symbol as provided by ISymbol.Name is the same as the name of
+ // the original type symbol that is being replaced by this type symbol.
+ // The "#{generation}" suffix is appended to the TypeDef name in the metadata writer,
+ // but not to the attribute value.
+ var originalType = this;
+
+ AddSynthesizedAttribute(
+ ref attributes,
+ compilation.TrySynthesizeAttribute(
+ WellKnownMember.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute__ctor,
+ ImmutableArray.Create(new TypedConstant(compilation.GetWellKnownType(WellKnownType.System_Type), TypedConstantKind.Type, originalType)),
+ isOptionalUse: true));
+ }
}
#endregion
diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTestBase.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTestBase.cs
index 0990411a4ccea..ba8a0e8c0f7e6 100644
--- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTestBase.cs
+++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTestBase.cs
@@ -145,27 +145,48 @@ internal static EntityHandle Handle(int rowNumber, TableIndex table)
internal static bool IsDefinition(HandleKind kind)
=> kind is not (HandleKind.AssemblyReference or HandleKind.ModuleReference or HandleKind.TypeReference or HandleKind.MemberReference or HandleKind.TypeSpecification or HandleKind.MethodSpecification);
+ ///
+ /// Checks that the EncLog contains specified rows.
+ /// Any default values in the expected are ignored to facilitate conditional code.
+ ///
internal static void CheckEncLog(MetadataReader reader, params EditAndContinueLogEntry[] rows)
{
- AssertEx.Equal(rows, reader.GetEditAndContinueLogEntries(), itemInspector: EncLogRowToString);
+ AssertEx.Equal(
+ rows.Where(r => r.Handle != default),
+ reader.GetEditAndContinueLogEntries(), itemInspector: EncLogRowToString);
}
///
/// Checks that the EncLog contains specified definition rows. References are ignored as they are usually not interesting to validate. They are emitted as needed.
+ /// Any default values in the expected are ignored to facilitate conditional code.
///
internal static void CheckEncLogDefinitions(MetadataReader reader, params EditAndContinueLogEntry[] rows)
{
- AssertEx.Equal(rows, reader.GetEditAndContinueLogEntries().Where(e => IsDefinition(e.Handle.Kind)), itemInspector: EncLogRowToString);
+ AssertEx.Equal(
+ rows.Where(r => r.Handle != default),
+ reader.GetEditAndContinueLogEntries().Where(e => IsDefinition(e.Handle.Kind)), itemInspector: EncLogRowToString);
}
+ ///
+ /// Checks that the EncMap contains specified handles.
+ /// Any default values in the expected are ignored to facilitate conditional code.
+ ///
internal static void CheckEncMap(MetadataReader reader, params EntityHandle[] handles)
{
- AssertEx.Equal(handles, reader.GetEditAndContinueMapEntries(), itemInspector: EncMapRowToString);
+ AssertEx.Equal(
+ handles.Where(h => h != default),
+ reader.GetEditAndContinueMapEntries(), itemInspector: EncMapRowToString);
}
+ ///
+ /// Checks that the EncMap contains specified definition handles. References are ignored as they are usually not interesting to validate. They are emitted as needed.
+ /// Any default values in the expected are ignored to facilitate conditional code.
+ ///
internal static void CheckEncMapDefinitions(MetadataReader reader, params EntityHandle[] handles)
{
- AssertEx.Equal(handles, reader.GetEditAndContinueMapEntries().Where(e => IsDefinition(e.Kind)), itemInspector: EncMapRowToString);
+ AssertEx.Equal(
+ handles.Where(h => h != default),
+ reader.GetEditAndContinueMapEntries().Where(e => IsDefinition(e.Kind)), itemInspector: EncMapRowToString);
}
internal static void CheckAttributes(MetadataReader reader, params CustomAttributeRow[] rows)
@@ -203,7 +224,7 @@ private static void CheckNames(
Func toHandle,
string[] expectedNames)
{
- var aggregator = new MetadataAggregator(readers[0], readers.Skip(1).ToArray());
+ var aggregator = GetAggregator(readers);
AssertEx.Equal(expectedNames, entityHandles.Select(handle =>
{
@@ -215,6 +236,27 @@ private static void CheckNames(
}));
}
+ public static void CheckBlobValue(IList readers, BlobHandle valueHandle, byte[] expectedValue)
+ {
+ var aggregator = GetAggregator(readers);
+
+ var genHandle = (BlobHandle)aggregator.GetGenerationHandle(valueHandle, out int blobGeneration);
+ var attributeData = readers[blobGeneration].GetBlobBytes(genHandle);
+ AssertEx.Equal(expectedValue, attributeData);
+ }
+
+ public static void CheckStringValue(IList readers, StringHandle valueHandle, string expectedValue)
+ {
+ var aggregator = GetAggregator(readers);
+
+ var genHandle = (StringHandle)aggregator.GetGenerationHandle(valueHandle, out int blobGeneration);
+ var attributeData = readers[blobGeneration].GetString(genHandle);
+ AssertEx.Equal(expectedValue, attributeData);
+ }
+
+ public static MetadataAggregator GetAggregator(IList readers)
+ => new MetadataAggregator(readers[0], readers.Skip(1).ToArray());
+
internal static string EncLogRowToString(EditAndContinueLogEntry row)
{
TableIndex tableIndex;
diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs
index e16e24a235ee3..29af80774efc0 100644
--- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs
@@ -12,6 +12,7 @@
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
+using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
@@ -3468,31 +3469,58 @@ class C
Handle(5, TableIndex.CustomAttribute));
}
- [Fact]
- public void ReplaceType()
+ public static string MetadataUpdateOriginalTypeAttributeSource = @"
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple=false, Inherited=false)]
+ public class MetadataUpdateOriginalTypeAttribute : Attribute
+ {
+ public MetadataUpdateOriginalTypeAttribute(Type originalType) => OriginalType = originalType;
+ public Type OriginalType { get; }
+ }
+}
+";
+
+ public static string BadMetadataUpdateOriginalTypeAttributeSource = @"
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple=false, Inherited=false)]
+ public class MetadataUpdateOriginalTypeAttribute : Attribute
+ {
+ public MetadataUpdateOriginalTypeAttribute(object originalType) => OriginalType = (Type)originalType;
+ public Type OriginalType { get; }
+ }
+}
+";
+
+ [Theory]
+ [CombinatorialData]
+ public void ReplaceType(bool hasAttribute)
{
+ // using incorrect definition of the attribute so that it's easier to compare the two emit results (having and attribute and not having one):
+ var attributeSource = hasAttribute ? MetadataUpdateOriginalTypeAttributeSource : BadMetadataUpdateOriginalTypeAttributeSource;
+
var source0 = @"
class C
{
void F(int x) {}
-}
-";
+}" + attributeSource;
var source1 = @"
class C
{
void F(int x, int y) { }
-}";
+}" + attributeSource;
var source2 = @"
class C
{
void F(int x, int y) { System.Console.WriteLine(1); }
-}";
+}" + attributeSource;
var source3 = @"
[System.Obsolete]
class C
{
void F(int x, int y) { System.Console.WriteLine(2); }
-}";
+}" + attributeSource;
var compilation0 = CreateCompilation(source0, options: TestOptions.DebugDll, targetFramework: TargetFramework.NetStandard20);
var compilation1 = compilation0.WithSource(source1);
@@ -3511,77 +3539,99 @@ class C
using var md0 = ModuleMetadata.CreateFromImage(bytes0);
var reader0 = md0.MetadataReader;
- CheckNames(reader0, reader0.GetTypeDefNames(), "", "C");
+ CheckNames(reader0, reader0.GetTypeDefNames(), "", "C", "MetadataUpdateOriginalTypeAttribute");
var generation0 = EmitBaseline.CreateInitialBaseline(
md0,
EmptyLocalsProvider);
+ var baseTypeCount = reader0.TypeDefinitions.Count;
+ var baseMethodCount = reader0.MethodDefinitions.Count;
+ var baseAttributeCount = reader0.CustomAttributes.Count;
+ var baseParameterCount = reader0.GetParameters().Count();
+
+ Assert.Equal(3, baseTypeCount);
+ Assert.Equal(4, baseMethodCount);
+ Assert.Equal(7, baseAttributeCount);
+ Assert.Equal(2, baseParameterCount);
+
+ var attributeTypeDefHandle = reader0.TypeDefinitions.Single(d => reader0.StringComparer.Equals(reader0.GetTypeDefinition(d).Name, "MetadataUpdateOriginalTypeAttribute"));
+ var attributeCtorDefHandle = reader0.MethodDefinitions.Single(d =>
+ {
+ var methodDef = reader0.GetMethodDefinition(d);
+ return methodDef.GetDeclaringType() == attributeTypeDefHandle && reader0.StringComparer.Equals(methodDef.Name, ".ctor");
+ });
+
+ void ValidateReplacedType(CompilationDifference diff, MetadataReader[] readers)
+ {
+ var generation = diff.NextGeneration.Ordinal;
+ var reader = readers[generation];
+
+ CheckNames(readers, diff.EmitResult.ChangedTypes, "C#" + generation);
+ CheckNames(readers, reader.GetTypeDefNames(), "C#" + generation);
+
+ CheckEncLogDefinitions(reader,
+ Row(baseTypeCount + generation, TableIndex.TypeDef, EditAndContinueOperation.Default), // adding a type def
+ Row(baseTypeCount + generation, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(baseMethodCount + generation * 2 - 1, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(baseTypeCount + generation, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(baseMethodCount + generation * 2, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(baseMethodCount + generation * 2 - 1, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
+ Row(baseParameterCount + generation * 2 - 1, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(baseMethodCount + generation * 2 - 1, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
+ Row(baseParameterCount + generation * 2, TableIndex.Param, EditAndContinueOperation.Default),
+ hasAttribute ? Row(baseAttributeCount + generation, TableIndex.CustomAttribute, EditAndContinueOperation.Default) : default); // adding a new attribute row for attribute on C#* definition
+
+ CheckEncMapDefinitions(reader,
+ Handle(baseTypeCount + generation, TableIndex.TypeDef),
+ Handle(baseMethodCount + generation * 2 - 1, TableIndex.MethodDef),
+ Handle(baseMethodCount + generation * 2, TableIndex.MethodDef),
+ Handle(baseParameterCount + generation * 2 - 1, TableIndex.Param),
+ Handle(baseParameterCount + generation * 2, TableIndex.Param),
+ hasAttribute ? Handle(baseAttributeCount + generation, TableIndex.CustomAttribute) : default);
+
+ var newTypeDefHandle = reader.TypeDefinitions.Single();
+ var newTypeDef = reader.GetTypeDefinition(newTypeDefHandle);
+ CheckStringValue(readers, newTypeDef.Name, "C#" + generation);
+
+ if (hasAttribute)
+ {
+ var attribute = reader.GetCustomAttribute(reader.CustomAttributes.Single());
+
+ // parent should be C#1
+ var aggregator = GetAggregator(readers);
+ var parentHandle = aggregator.GetGenerationHandle(attribute.Parent, out var parentGeneration);
+ Assert.Equal(generation, parentGeneration);
+ Assert.Equal(newTypeDefHandle, parentHandle);
+
+ // attribute contructor should match
+ var ctorHandle = aggregator.GetGenerationHandle(attribute.Constructor, out var ctorGeneration);
+ Assert.Equal(0, ctorGeneration);
+ Assert.Equal(attributeCtorDefHandle, ctorHandle);
+
+ // The attribute value encodes serialized type name. It should be the base name "C", not "C#1".
+ CheckBlobValue(readers, attribute.Value, new byte[] { 0x01, 0x00, 0x01, (byte)'C', 0x00, 0x00 });
+ }
+ }
+
// This update emulates "Reloadable" type behavior - a new type is generated instead of updating the existing one.
var diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(
SemanticEdit.Create(SemanticEditKind.Replace, null, c1)));
- // Verify delta metadata contains expected rows.
using var md1 = diff1.GetMetadata();
- var reader1 = md1.Reader;
- var readers = new[] { reader0, reader1 };
-
- CheckNames(readers, reader1.GetTypeDefNames(), "C#1");
- CheckNames(readers, diff1.EmitResult.ChangedTypes, "C#1");
-
- CheckEncLogDefinitions(reader1,
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
- Row(2, TableIndex.Param, EditAndContinueOperation.Default),
- Row(3, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
- Row(3, TableIndex.Param, EditAndContinueOperation.Default));
+ ValidateReplacedType(diff1, new[] { reader0, md1.Reader });
- CheckEncMapDefinitions(reader1,
- Handle(3, TableIndex.TypeDef),
- Handle(3, TableIndex.MethodDef),
- Handle(4, TableIndex.MethodDef),
- Handle(2, TableIndex.Param),
- Handle(3, TableIndex.Param));
-
- // This update emulates "Reloadable" type behavior - a new type is generated instead of updating the existing one.
var diff2 = compilation2.EmitDifference(
diff1.NextGeneration,
ImmutableArray.Create(
SemanticEdit.Create(SemanticEditKind.Replace, null, c2)));
- // Verify delta metadata contains expected rows.
using var md2 = diff2.GetMetadata();
- var reader2 = md2.Reader;
- readers = new[] { reader0, reader1, reader2 };
-
- CheckNames(readers, reader2.GetTypeDefNames(), "C#2");
- CheckNames(readers, diff2.EmitResult.ChangedTypes, "C#2");
-
- CheckEncLogDefinitions(reader2,
- Row(4, TableIndex.TypeDef, EditAndContinueOperation.Default),
- Row(4, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(4, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
- Row(4, TableIndex.Param, EditAndContinueOperation.Default),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
- Row(5, TableIndex.Param, EditAndContinueOperation.Default));
+ ValidateReplacedType(diff2, new[] { reader0, md1.Reader, md2.Reader });
- CheckEncMapDefinitions(reader2,
- Handle(4, TableIndex.TypeDef),
- Handle(5, TableIndex.MethodDef),
- Handle(6, TableIndex.MethodDef),
- Handle(4, TableIndex.Param),
- Handle(5, TableIndex.Param));
-
- // This update is an EnC update - even reloadable types are update in-place
+ // This update is an EnC update - even reloadable types are updated in-place
var diff3 = compilation3.EmitDifference(
diff2.NextGeneration,
ImmutableArray.Create(
@@ -3591,24 +3641,28 @@ class C
// Verify delta metadata contains expected rows.
using var md3 = diff3.GetMetadata();
var reader3 = md3.Reader;
- readers = new[] { reader0, reader1, reader2, reader3 };
+ var readers = new[] { reader0, md1.Reader, md2.Reader, reader3 };
CheckNames(readers, reader3.GetTypeDefNames(), "C#2");
CheckNames(readers, diff3.EmitResult.ChangedTypes, "C#2");
+ // Obsolete attribute is added. MetadataUpdateOriginalTypeAttribute is still present on the type.
CheckEncLogDefinitions(reader3,
- Row(4, TableIndex.TypeDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(4, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default),
+ Row(7, TableIndex.MethodDef, EditAndContinueOperation.Default),
Row(5, TableIndex.Param, EditAndContinueOperation.Default),
- Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default));
+ Row(6, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(hasAttribute ? 9 : 8, TableIndex.CustomAttribute, EditAndContinueOperation.Default));
CheckEncMapDefinitions(reader3,
- Handle(4, TableIndex.TypeDef),
- Handle(5, TableIndex.MethodDef),
- Handle(4, TableIndex.Param),
+ Handle(5, TableIndex.TypeDef),
+ Handle(7, TableIndex.MethodDef),
Handle(5, TableIndex.Param),
- Handle(4, TableIndex.CustomAttribute));
+ Handle(6, TableIndex.Param),
+ Handle(hasAttribute ? 9 : 8, TableIndex.CustomAttribute));
+
+ // Obsolete attribute:
+ CheckBlobValue(readers, reader3.GetCustomAttribute(reader3.CustomAttributes.First()).Value, new byte[] { 0x01, 0x00, 0x00, 0x00 });
}
[Fact]
diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs
index c69bc5d933447..87652853a79d2 100644
--- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs
@@ -618,6 +618,7 @@ public void AllWellKnownTypes()
case WellKnownType.System_MemoryExtensions:
case WellKnownType.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute:
case WellKnownType.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute:
+ case WellKnownType.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute:
// Not yet in the platform.
continue;
case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation:
@@ -983,6 +984,7 @@ public void AllWellKnownTypeMembers()
case WellKnownMember.System_MemoryExtensions__AsSpan_String:
case WellKnownMember.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute__ctor:
case WellKnownMember.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor:
+ case WellKnownMember.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute__ctor:
// Not yet in the platform.
continue;
case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile:
diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolChanges.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolChanges.cs
index 94ef3985ed478..34fd9e39dd98a 100644
--- a/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolChanges.cs
+++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/SymbolChanges.cs
@@ -98,10 +98,13 @@ private ImmutableArray ToInternalSymbolArray(ISet symb
return internalSymbols.ToImmutableAndFree();
}
+ public bool IsReplaced(ISymbol symbol)
+ => _replacedSymbols.Contains(symbol);
+
public bool IsReplaced(IDefinition definition)
{
var symbol = definition.GetInternalSymbol();
- return symbol is not null && _replacedSymbols.Contains(symbol.GetISymbol());
+ return symbol is not null && IsReplaced(symbol.GetISymbol());
}
///
diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs
index 7c993b1e31200..6c918ede9dda6 100644
--- a/src/Compilers/Core/Portable/WellKnownMember.cs
+++ b/src/Compilers/Core/Portable/WellKnownMember.cs
@@ -532,6 +532,7 @@ internal enum WellKnownMember
System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor,
System_MissingMethodException__ctor,
+ System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute__ctor,
Count
diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs
index 42caed3424a60..96b50b609133b 100644
--- a/src/Compilers/Core/Portable/WellKnownMembers.cs
+++ b/src/Compilers/Core/Portable/WellKnownMembers.cs
@@ -3653,6 +3653,13 @@ static WellKnownMembers()
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void,
+ // MetadataUpdateOriginalTypeAttribute__ctor
+ (byte)MemberFlags.Constructor, // Flags
+ (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId
+ 0, // Arity
+ 1, // Method Signature
+ (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type
+ (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Type,
};
string[] allNames = new string[(int)WellKnownMember.Count]
@@ -4103,13 +4110,14 @@ static WellKnownMembers()
"ToStringAndClear", // System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear
".ctor", // System_Runtime_CompilerServices_RequiredMemberAttribute__ctor
".ctor", // System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute__ctor
- ".ctor", // System_Runtime_CompilerServices_LifetimeAttribute__ctor
+ ".ctor", // System_Runtime_CompilerServices_LifetimeAttribute__ctor
"SequenceEqual", // System_MemoryExtensions__SequenceEqual_Span_T
"SequenceEqual", // System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T
"AsSpan", // System_MemoryExtensions__AsSpan_String
".ctor", // System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute_ctor
".ctor", // System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor
".ctor", // System_MissingMethodException__ctor
+ ".ctor", // System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute
};
s_descriptors = MemberDescriptor.InitializeFromStream(new System.IO.MemoryStream(initializationBytes, writable: false), allNames);
diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs
index 30af781d8f281..199b7d442e6cf 100644
--- a/src/Compilers/Core/Portable/WellKnownTypes.cs
+++ b/src/Compilers/Core/Portable/WellKnownTypes.cs
@@ -326,6 +326,7 @@ internal enum WellKnownType
System_Diagnostics_CodeAnalysis_UnscopedRefAttribute,
System_MissingMethodException,
+ System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute,
NextAvailable,
// Remember to update the AllWellKnownTypes tests when making changes here
@@ -643,6 +644,7 @@ internal static class WellKnownTypes
"System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute",
"System.Diagnostics.CodeAnalysis.UnscopedRefAttribute",
"System.MissingMethodException",
+ "System.Runtime.CompilerServices.MetadataUpdateOriginalTypeAttribute",
};
private static readonly Dictionary s_nameToTypeIdMap = new Dictionary((int)Count);
diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb
index 7532fe56fb447..17e19e02660bc 100644
--- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb
+++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb
@@ -553,7 +553,8 @@ End Namespace
WellKnownType.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute,
WellKnownType.System_Runtime_CompilerServices_ScopedRefAttribute,
WellKnownType.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute,
- WellKnownType.System_MemoryExtensions
+ WellKnownType.System_MemoryExtensions,
+ WellKnownType.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute
' Not available on all platforms.
Continue For
Case WellKnownType.ExtSentinel
@@ -625,7 +626,8 @@ End Namespace
WellKnownType.System_MemoryExtensions,
WellKnownType.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute,
WellKnownType.System_Runtime_CompilerServices_ScopedRefAttribute,
- WellKnownType.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute
+ WellKnownType.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute,
+ WellKnownType.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute
' Not available on all platforms.
Continue For
Case WellKnownType.ExtSentinel
@@ -722,7 +724,8 @@ End Namespace
WellKnownMember.System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T,
WellKnownMember.System_MemoryExtensions__AsSpan_String,
WellKnownMember.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute__ctor,
- WellKnownMember.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor
+ WellKnownMember.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor,
+ WellKnownMember.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute__ctor
' Not available yet, but will be in upcoming release.
Continue For
Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile,
@@ -875,7 +878,8 @@ End Namespace
WellKnownMember.System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T,
WellKnownMember.System_MemoryExtensions__AsSpan_String,
WellKnownMember.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute__ctor,
- WellKnownMember.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor
+ WellKnownMember.System_Diagnostics_CodeAnalysis_UnscopedRefAttribute__ctor,
+ WellKnownMember.System_Runtime_CompilerServices_MetadataUpdateOriginalTypeAttribute__ctor
' Not available yet, but will be in upcoming release.
Continue For
Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile,