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,