From a3ada0cb72022c91b315aed1e7ab9d3ec2c91b02 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Tue, 27 Oct 2020 09:42:44 -0700 Subject: [PATCH 1/4] Further optimize FindValidCloneMethod https://github.com/dotnet/roslyn/pull/48935 optimizes one path that hits FindValidCloneMethod, but there are others that could do with the same fast-path optimization. In order to accomplish that, I introduced a new HasPossibleCloneMethod on NamedTypeSymbol, that returns whether the type _could_ have a method on it that is a valid clone method. For source types, this is a quick syntax check to see if it's a record. For metadata types, it's a check on just the member names for something with the right name. This should prevent us from unnecessarily loading all method signatures from metadata unnecessarily whenever we check for a clone method. --- .../PublicSymbols/AnonymousType.TypePublicSymbol.cs | 2 ++ .../AnonymousType.TemplateSymbol.cs | 2 ++ .../CSharp/Portable/Symbols/ErrorTypeSymbol.cs | 1 + .../Symbols/Metadata/PE/PENamedTypeSymbol.cs | 13 +++---------- .../CSharp/Portable/Symbols/NamedTypeSymbol.cs | 7 +++++++ .../Symbols/Source/SourceMemberContainerSymbol.cs | 7 +++++++ .../Synthesized/Records/SynthesizedRecordClone.cs | 10 +++++++++- .../Symbols/Synthesized/SynthesizedContainer.cs | 2 ++ .../SynthesizedEmbeddedAttributeSymbol.cs | 1 + .../Symbols/Wrapped/WrappedNamedTypeSymbol.cs | 2 ++ 10 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs index 6e5e317844852..1904a5bf76d77 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs @@ -347,6 +347,8 @@ public override int GetHashCode() { return this.TypeDescriptor.GetHashCode(); } + + internal override bool HasPossibleWellKnownCloneMethod() => false; } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs index 7691f415e0b57..cec33a084a910 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs @@ -507,6 +507,8 @@ private SynthesizedAttributeData TrySynthesizeDebuggerDisplayAttribute() WellKnownMember.System_Diagnostics_DebuggerDisplayAttribute__Type, new TypedConstant(Manager.System_String, TypedConstantKind.Primitive, "")))); } + + internal override bool HasPossibleWellKnownCloneMethod() => false; } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index 6216204840720..820ece0cc1bcf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs @@ -544,6 +544,7 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn } internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; } internal abstract class SubstitutedErrorTypeSymbol : ErrorTypeSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index 7f9078ed0e68d..b55e9f1d427bb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -560,16 +560,6 @@ internal override bool IsRecord { get { - // First, do a check to see if there are even any members named $. If we have to actually find the clone - // method, it can be expensive, because we have to load all the members. MemberNames just loads the strings, which - // is much cheaper. - if (!MemberNames.Contains(WellKnownMemberNames.CloneMethodName)) - { - return false; - } - - // There exists a member named $. We still need to check to see if it's actually a valid clone method, but - // there's no getting around that now. HashSet useSiteDiagnostics = null; return SynthesizedRecordClone.FindValidCloneMethod(this, ref useSiteDiagnostics) != null; } @@ -1429,6 +1419,9 @@ public override ImmutableArray GetMembers(string name) return m; } + internal override bool HasPossibleWellKnownCloneMethod() + => MemberNames.Contains(WellKnownMemberNames.CloneMethodName); + internal override FieldSymbol FixedElementField { get diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index 4f343caa1af1a..2fdefb5df1595 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -511,6 +511,13 @@ internal abstract bool MangleName /// no members with this name, returns an empty ImmutableArray. Never returns null. public abstract override ImmutableArray GetMembers(string name); + /// + /// A lightweight check for whether this type has a possible clone method. This is less costly than GetMembers, + /// particularly for PE symbols, and can be used as a cheap heuristic for whether to fully search through all + /// members of this type for a valid clone method. + /// + internal abstract bool HasPossibleWellKnownCloneMethod(); + internal virtual ImmutableArray GetSimpleNonTypeMembers(string name) { return GetMembers(name); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 1412a595ad398..ad72c2d4400f4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -1249,6 +1249,13 @@ public sealed override ImmutableArray GetMembers(string name) return ImmutableArray.Empty; } + + internal override bool HasPossibleWellKnownCloneMethod() + // For source symbols, there can only be a valid clone method if this is a record, which is a + // simple syntax check. This will need to change when we generalize cloning, but it's a good + // heuristic for now. + => IsRecord; + internal override ImmutableArray GetSimpleNonTypeMembers(string name) { if (_lazyMembersDictionary != null || declaration.MemberNames.Contains(name)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs index 30d7294af46e7..123ce5c32593c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs @@ -144,7 +144,15 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, internal static MethodSymbol? FindValidCloneMethod(TypeSymbol containingType, ref HashSet? useSiteDiagnostics) { - if (containingType.IsObjectType()) + if (containingType.IsObjectType() || containingType is not NamedTypeSymbol containingNamedType) + { + return null; + } + + // If this symbol is from metadata, getting all members can cause us to realize a lot of structures that we otherwise + // don't have to. Optimize for the common case here of there not being a method named $. If there is a method + // with that name, it's most likely the one we're interested in, and we can't get around loading everything to find it. + if (!containingNamedType.HasPossibleWellKnownCloneMethod()) { return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs index b86792454fe61..f0eaf83ee9696 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs @@ -221,5 +221,7 @@ internal override IEnumerable GetFieldsToEmit() internal sealed override NamedTypeSymbol AsNativeInteger() => throw ExceptionUtilities.Unreachable; internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; + + internal override bool HasPossibleWellKnownCloneMethod() => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs index 18d995dec2eeb..d7bfe9d5858e2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs @@ -179,6 +179,7 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r internal sealed override NamedTypeSymbol AsNativeInteger() => throw ExceptionUtilities.Unreachable; internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; + internal override bool HasPossibleWellKnownCloneMethod() => false; } /// diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs index c2531dae3f9ee..173b45f9a41d0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs @@ -256,5 +256,7 @@ internal override bool GetGuidString(out string guidString) { return _underlyingType.GetGuidString(out guidString); } + + internal override bool HasPossibleWellKnownCloneMethod() => _underlyingType.HasPossibleWellKnownCloneMethod(); } } From 5d1e73edaa4503f409f04bdc8916a1183f17eee1 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Tue, 27 Oct 2020 12:13:40 -0700 Subject: [PATCH 2/4] Add missing overrides. --- src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs | 1 + .../Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index 9906b4887e430..c1920be354944 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs @@ -325,5 +325,6 @@ internal override AttributeUsageInfo GetAttributeUsageInfo() internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; } } diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs index a6e45edd4b8ff..066f61287360c 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs @@ -349,6 +349,7 @@ internal override bool IsInterface internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; [Conditional("DEBUG")] internal static void VerifyTypeParameters(Symbol container, ImmutableArray typeParameters) From 51c2daecaa2df4e801034148e62f9c813a67c7a4 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Thu, 29 Oct 2020 13:31:10 -0700 Subject: [PATCH 3/4] Formatting feedback. --- .../Symbols/Source/SourceMemberContainerSymbol.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index ad72c2d4400f4..a4778b897e254 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -1249,11 +1249,12 @@ public sealed override ImmutableArray GetMembers(string name) return ImmutableArray.Empty; } - + /// + /// For source symbols, there can only be a valid clone method if this is a record, which is a + /// simple syntax check. This will need to change when we generalize cloning, but it's a good + /// heuristic for now. + /// internal override bool HasPossibleWellKnownCloneMethod() - // For source symbols, there can only be a valid clone method if this is a record, which is a - // simple syntax check. This will need to change when we generalize cloning, but it's a good - // heuristic for now. => IsRecord; internal override ImmutableArray GetSimpleNonTypeMembers(string name) From 5d046a35c378072afdb151f9e42f1d365e47e8b6 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Mon, 2 Nov 2020 11:12:20 -0800 Subject: [PATCH 4/4] Move HasPossibleWellKnownCloneMethod implementations next to IsRecord implementations, seal where possible. --- .../Portable/Lowering/AsyncRewriter/AsyncStateMachine.cs | 1 + .../ClosureConversion/SynthesizedClosureEnvironment.cs | 1 + .../Lowering/IteratorRewriter/IteratorStateMachine.cs | 1 + .../Portable/Lowering/LocalRewriter/DynamicSiteContainer.cs | 1 + src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs | 4 ++-- .../CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs | 2 +- .../CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs | 3 ++- .../Symbols/Retargeting/RetargetingNamedTypeSymbol.cs | 3 ++- .../CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs | 1 + .../CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs | 3 ++- .../Portable/Symbols/Synthesized/SynthesizedContainer.cs | 2 -- .../Portable/Symbols/Synthesized/SynthesizedDelegateSymbol.cs | 1 + .../Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs | 2 +- .../SynthesizedEmbeddedNativeIntegerAttributeSymbol.cs | 1 + .../Synthesized/SynthesizedEmbeddedNullableAttributeSymbol.cs | 1 + .../SynthesizedEmbeddedNullableContextAttributeSymbol.cs | 1 + .../SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol.cs | 1 + .../CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs | 2 -- 18 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncStateMachine.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncStateMachine.cs index 9725e923e5be3..e349cd51c54d6 100644 --- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncStateMachine.cs +++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncStateMachine.cs @@ -72,6 +72,7 @@ internal override MethodSymbol Constructor } internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; internal override ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList basesBeingResolved) { diff --git a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureEnvironment.cs b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureEnvironment.cs index 3cac018a722a3..34c834a3b9d07 100644 --- a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureEnvironment.cs +++ b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureEnvironment.cs @@ -142,5 +142,6 @@ internal override IEnumerable GetFieldsToEmit() IMethodSymbolInternal ISynthesizedMethodBodyImplementationSymbol.Method => _topLevelMethod; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; } } diff --git a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorStateMachine.cs b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorStateMachine.cs index 3787ed5f3accc..ed2cac2c961be 100644 --- a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorStateMachine.cs +++ b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorStateMachine.cs @@ -61,5 +61,6 @@ internal override ImmutableArray InterfacesNoUseSiteDiagnostics internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics => ContainingAssembly.GetSpecialType(SpecialType.System_Object); internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; } } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/DynamicSiteContainer.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/DynamicSiteContainer.cs index f1a00c4858e74..520680e26e269 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/DynamicSiteContainer.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/DynamicSiteContainer.cs @@ -37,6 +37,7 @@ public sealed override bool AreLocalsZeroed } internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; bool ISynthesizedMethodBodyImplementationSymbol.HasMethodBodyDependency { diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index 820ece0cc1bcf..97e05bbfefa42 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs @@ -543,8 +543,8 @@ protected sealed override ITypeSymbol CreateITypeSymbol(CodeAnalysis.NullableAnn return new PublicModel.ErrorTypeSymbol(this, nullableAnnotation); } - internal override bool IsRecord => false; - internal override bool HasPossibleWellKnownCloneMethod() => false; + internal sealed override bool IsRecord => false; + internal sealed override bool HasPossibleWellKnownCloneMethod() => false; } internal abstract class SubstitutedErrorTypeSymbol : ErrorTypeSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index b55e9f1d427bb..09d6fedf4fb86 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -1419,7 +1419,7 @@ public override ImmutableArray GetMembers(string name) return m; } - internal override bool HasPossibleWellKnownCloneMethod() + internal sealed override bool HasPossibleWellKnownCloneMethod() => MemberNames.Contains(WellKnownMemberNames.CloneMethodName); internal override FieldSymbol FixedElementField diff --git a/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs index 9c2b9478e4760..4a3b03191b48b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs @@ -160,7 +160,8 @@ ImmutableArray makeMembers(ImmutableArray underlyingMembers) internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => _underlyingType; - internal override bool IsRecord => false; + internal sealed override bool IsRecord => false; + internal sealed override bool HasPossibleWellKnownCloneMethod() => false; internal override bool Equals(TypeSymbol? other, TypeCompareKind comparison, IReadOnlyDictionary? isValueTypeOverrideOpt = null) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs index eee6bf44d91bd..70b69e2fbd025 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs @@ -376,6 +376,7 @@ public sealed override bool AreLocalsZeroed internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; - internal override bool IsRecord => _underlyingType.IsRecord; + internal sealed override bool IsRecord => _underlyingType.IsRecord; + internal sealed override bool HasPossibleWellKnownCloneMethod() => _underlyingType.HasPossibleWellKnownCloneMethod(); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs index 24ce60bc809f7..02c8d67b4a0cf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs @@ -240,5 +240,6 @@ public sealed override bool AreLocalsZeroed => throw ExceptionUtilities.Unreachable; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs index ad84d76ad10ac..b89065f06a1cf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs @@ -398,6 +398,7 @@ internal override IEnumerable GetCustomAttributesToEmit(PEM internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; - internal override bool IsRecord => _underlyingType.IsRecord; + internal sealed override bool IsRecord => _underlyingType.IsRecord; + internal sealed override bool HasPossibleWellKnownCloneMethod() => _underlyingType.HasPossibleWellKnownCloneMethod(); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs index f0eaf83ee9696..b86792454fe61 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs @@ -221,7 +221,5 @@ internal override IEnumerable GetFieldsToEmit() internal sealed override NamedTypeSymbol AsNativeInteger() => throw ExceptionUtilities.Unreachable; internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; - - internal override bool HasPossibleWellKnownCloneMethod() => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedDelegateSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedDelegateSymbol.cs index 2d202e720d3f7..73bec1612d0ba 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedDelegateSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedDelegateSymbol.cs @@ -89,6 +89,7 @@ public sealed override bool AreLocalsZeroed } internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; private sealed class DelegateConstructor : SynthesizedInstanceConstructor { diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs index d7bfe9d5858e2..d6caccba24aed 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs @@ -179,7 +179,6 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r internal sealed override NamedTypeSymbol AsNativeInteger() => throw ExceptionUtilities.Unreachable; internal sealed override NamedTypeSymbol NativeIntegerUnderlyingType => null; - internal override bool HasPossibleWellKnownCloneMethod() => false; } /// @@ -202,6 +201,7 @@ public SynthesizedEmbeddedAttributeSymbol( public override ImmutableArray Constructors => _constructors; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; } internal sealed class SynthesizedEmbeddedAttributeConstructorSymbol : SynthesizedInstanceConstructor diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNativeIntegerAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNativeIntegerAttributeSymbol.cs index b193c24d03008..83f6876dcd985 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNativeIntegerAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNativeIntegerAttributeSymbol.cs @@ -62,6 +62,7 @@ public SynthesizedEmbeddedNativeIntegerAttributeSymbol( public override ImmutableArray Constructors => _constructors; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; internal override AttributeUsageInfo GetAttributeUsageInfo() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableAttributeSymbol.cs index dd25985e6fd8c..dd04f08330013 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableAttributeSymbol.cs @@ -66,6 +66,7 @@ public SynthesizedEmbeddedNullableAttributeSymbol( public override ImmutableArray Constructors => _constructors; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; internal override AttributeUsageInfo GetAttributeUsageInfo() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableContextAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableContextAttributeSymbol.cs index 67829ca6ae407..135cbe84eb2f3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableContextAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullableContextAttributeSymbol.cs @@ -50,6 +50,7 @@ public SynthesizedEmbeddedNullableContextAttributeSymbol( public override ImmutableArray Constructors => _constructors; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; internal override AttributeUsageInfo GetAttributeUsageInfo() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol.cs index e7f25c1984ac2..9f82052ed245f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol.cs @@ -50,6 +50,7 @@ public SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol( public override ImmutableArray Constructors => _constructors; internal override bool IsRecord => false; + internal override bool HasPossibleWellKnownCloneMethod() => false; internal override AttributeUsageInfo GetAttributeUsageInfo() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs index 173b45f9a41d0..c2531dae3f9ee 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs @@ -256,7 +256,5 @@ internal override bool GetGuidString(out string guidString) { return _underlyingType.GetGuidString(out guidString); } - - internal override bool HasPossibleWellKnownCloneMethod() => _underlyingType.HasPossibleWellKnownCloneMethod(); } }