From f200986e0648b684a0aacda9729f3ba504efee21 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 10 May 2023 11:11:16 -0700 Subject: [PATCH] Revert "Revert "Pack bits in SourceOrdinaryMethodSymbol into an existing bitflag structure we have for all source methods (#68132)"" This reverts commit d51ec383445a16fc25de208dbbc7965d276eb50a. --- .../SynthesizedClosureMethod.cs | 1 - .../Lowering/SynthesizedMethodBaseSymbol.cs | 8 +- .../Symbols/Source/SourceConstructorSymbol.cs | 15 +--- .../Source/SourceCustomEventAccessorSymbol.cs | 15 +--- .../Source/SourceDelegateMethodSymbol.cs | 8 +- .../Symbols/Source/SourceDestructorSymbol.cs | 22 ++---- .../Source/SourceEventAccessorSymbol.cs | 10 +-- .../Source/SourceMemberMethodSymbol.cs | 73 ++++++++++++++++--- .../Source/SourceOrdinaryMethodSymbol.cs | 32 +++----- .../Source/SourceOrdinaryMethodSymbolBase.cs | 7 +- .../Source/SourcePropertyAccessorSymbol.cs | 11 +-- .../SourceUserDefinedOperatorSymbolBase.cs | 9 +-- .../Records/SynthesizedPrimaryConstructor.cs | 3 +- .../SynthesizedRecordOrdinaryMethod.cs | 4 +- .../SynthesizedEventAccessorSymbol.cs | 2 +- ...ynthesizedSimpleProgramEntryPointSymbol.cs | 3 +- 16 files changed, 107 insertions(+), 116 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs index 7c8842384cb5c..94d75be8c52a3 100644 --- a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs +++ b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs @@ -218,7 +218,6 @@ protected override ImmutableArray ExtraSynthesizedRefParameters internal override bool InheritsBaseMethodAttributes => true; internal override bool GenerateDebugInfo => !this.IsAsync; - internal override bool IsExpressionBodied => false; internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree) { diff --git a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs index 409c5e74098a2..7362f09560c79 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs @@ -50,7 +50,8 @@ protected SynthesizedMethodBaseSymbol(NamedTypeSymbol containingType, returnsVoid: baseMethod.ReturnsVoid, isExtensionMethod: false, isNullableAnalysisEnabled: false, - isMetadataVirtualIgnoringModifiers: false); + isMetadataVirtualIgnoringModifiers: false, + isExpressionBodied: false); } protected void AssignTypeMapAndTypeParameters(TypeMap typeMap, ImmutableArray typeParameters) @@ -226,10 +227,5 @@ public sealed override bool IsImplicitlyDeclared { get { return true; } } - - internal override bool IsExpressionBodied - { - get { return false; } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs index 38371b2442a00..8fdcd2fbfd338 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -12,7 +12,6 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal sealed class SourceConstructorSymbol : SourceConstructorSymbolBase { - private readonly bool _isExpressionBodied; private readonly bool _hasThisInitializer; public static SourceConstructorSymbol CreateConstructorSymbol( @@ -35,14 +34,14 @@ private SourceConstructorSymbol( base(containingType, location, syntax, SyntaxFacts.HasYieldOperations(syntax)) { bool hasBlockBody = syntax.Body != null; - _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; - bool hasBody = hasBlockBody || _isExpressionBodied; + bool isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; + bool hasBody = hasBlockBody || isExpressionBodied; _hasThisInitializer = syntax.Initializer?.Kind() == SyntaxKind.ThisConstructorInitializer; bool modifierErrors; var declarationModifiers = this.MakeModifiers(syntax.Modifiers, methodKind, hasBody, location, diagnostics, out modifierErrors); - this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); if (syntax.Identifier.ValueText != containingType.Name) { @@ -163,14 +162,6 @@ internal override OneOrMany> GetAttributeDeclara return OneOrMany.Create(((ConstructorDeclarationSyntax)this.SyntaxNode).AttributeLists); } - internal override bool IsExpressionBodied - { - get - { - return _isExpressionBodied; - } - } - internal override bool IsNullableAnalysisEnabled() { return _hasThisInitializer ? diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs index 69ca26275e2ac..cc309bcce023e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs @@ -4,6 +4,7 @@ #nullable disable +using System; using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -32,7 +33,8 @@ internal SourceCustomEventAccessorSymbol( syntax.Keyword.GetLocation(), explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder: syntax.Kind() == SyntaxKind.AddAccessorDeclaration, isIterator: SyntaxFacts.HasYieldOperations(syntax.Body), - isNullableAnalysisEnabled: isNullableAnalysisEnabled) + isNullableAnalysisEnabled: isNullableAnalysisEnabled, + isExpressionBodied: syntax is { Body: null, ExpressionBody: not null }) { Debug.Assert(syntax != null); Debug.Assert(syntax.Kind() == SyntaxKind.AddAccessorDeclaration || syntax.Kind() == SyntaxKind.RemoveAccessorDeclaration); @@ -91,16 +93,5 @@ internal override bool GenerateDebugInfo { get { return true; } } - - internal override bool IsExpressionBodied - { - get - { - var syntax = GetSyntax(); - var hasBody = syntax.Body != null; - var hasExpressionBody = syntax.ExpressionBody != null; - return !hasBody && hasExpressionBody; - } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs index 28d792d0608a1..94a3fa6819e54 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -28,7 +28,8 @@ protected SourceDelegateMethodSymbol( : base(delegateType, syntax.GetReference(), location: syntax.Identifier.GetLocation(), isIterator: false) { _returnType = returnType; - this.MakeFlags(methodKind, declarationModifiers, _returnType.IsVoidType(), isExtensionMethod: false, isNullableAnalysisEnabled: false); + this.MakeFlags( + methodKind, declarationModifiers, _returnType.IsVoidType(), isExpressionBodied: false, isExtensionMethod: false, isNullableAnalysisEnabled: false); } internal sealed override ExecutableCodeBinder TryGetBodyBinder(BinderFactory binderFactoryOpt = null, bool ignoreAccessibility = false) => throw ExceptionUtilities.Unreachable(); @@ -176,11 +177,6 @@ public sealed override bool IsImplicitlyDeclared } } - internal override bool IsExpressionBodied - { - get { return false; } - } - internal override bool GenerateDebugInfo { get { return false; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs index 26dc833d7353d..c2071844d64e2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs @@ -14,7 +14,6 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols internal sealed class SourceDestructorSymbol : SourceMemberMethodSymbol { private TypeWithAnnotations _lazyReturnType; - private readonly bool _isExpressionBodied; internal SourceDestructorSymbol( SourceMemberContainerTypeSymbol containingType, @@ -28,17 +27,18 @@ internal SourceDestructorSymbol( bool modifierErrors; var declarationModifiers = MakeModifiers(syntax.Modifiers, location, diagnostics, out modifierErrors); - this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); + + bool hasBlockBody = syntax.Body != null; + bool isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; + + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); if (syntax.Identifier.ValueText != containingType.Name) { diagnostics.Add(ErrorCode.ERR_BadDestructorName, syntax.Identifier.GetLocation()); } - bool hasBlockBody = syntax.Body != null; - _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; - - if (hasBlockBody || _isExpressionBodied) + if (hasBlockBody || isExpressionBodied) { if (IsExtern) { @@ -46,7 +46,7 @@ internal SourceDestructorSymbol( } } - if (!modifierErrors && !hasBlockBody && !_isExpressionBodied && !IsExtern) + if (!modifierErrors && !hasBlockBody && !isExpressionBodied && !IsExtern) { diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this); } @@ -142,14 +142,6 @@ public override string Name get { return WellKnownMemberNames.DestructorName; } } - internal override bool IsExpressionBodied - { - get - { - return _isExpressionBodied; - } - } - internal override OneOrMany> GetAttributeDeclarations() { // destructors can't have return type attributes diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs index dc99d2054c40d..00d2c4cdd71d4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs @@ -29,7 +29,8 @@ public SourceEventAccessorSymbol( string aliasQualifierOpt, bool isAdder, bool isIterator, - bool isNullableAnalysisEnabled) + bool isNullableAnalysisEnabled, + bool isExpressionBodied) : base(@event.containingType, syntaxReference, location, isIterator) { _event = @event; @@ -56,6 +57,7 @@ public SourceEventAccessorSymbol( isAdder ? MethodKind.EventAdd : MethodKind.EventRemove, @event.Modifiers, returnsVoid: false, // until we learn otherwise (in LazyMethodChecks). + isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: @event.IsExplicitInterfaceImplementation && (@event.Modifiers & DeclarationModifiers.Static) == 0); @@ -246,11 +248,5 @@ protected string GetOverriddenAccessorName(SourceEventSymbol @event, bool isAdde return null; } - - internal override bool IsExpressionBodied - { - // Events cannot be expression-bodied - get { return false; } - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index a6288faa15dd7..82008e1cb88c4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -24,9 +24,10 @@ protected struct Flags { // We currently pack everything into a 32 bit int with the following layout: // - // | |n|vvv|yy|s|r|q|z|wwwww| + // | |a|b|e|n|vvv|yy|s|r|q|z|kk|wwwww| // // w = method kind. 5 bits. + // k = ref kind. 2 bits. // z = isExtensionMethod. 1 bit. // q = isMetadataVirtualIgnoringInterfaceChanges. 1 bit. // r = isMetadataVirtual. 1 bit. (At least as true as isMetadataVirtualIgnoringInterfaceChanges.) @@ -34,12 +35,20 @@ protected struct Flags // y = ReturnsVoid. 2 bits. // v = NullableContext. 3 bits. // n = IsNullableAnalysisEnabled. 1 bit. + // e = IsExpressionBody. 1 bit. + // b = HasAnyBody. 1 bit. + // a = IsVarArg. 1 bit private int _flags; private const int MethodKindOffset = 0; private const int MethodKindSize = 5; + private const int MethodKindMask = (1 << MethodKindSize) - 1; + + private const int RefKindOffset = MethodKindOffset + MethodKindSize; + private const int RefKindSize = 2; + private const int RefKindMask = (1 << RefKindSize) - 1; - private const int IsExtensionMethodOffset = MethodKindOffset + MethodKindSize; + private const int IsExtensionMethodOffset = RefKindOffset + RefKindSize; private const int IsExtensionMethodSize = 1; private const int IsMetadataVirtualIgnoringInterfaceChangesOffset = IsExtensionMethodOffset + IsExtensionMethodSize; @@ -56,24 +65,33 @@ protected struct Flags private const int NullableContextOffset = ReturnsVoidOffset + ReturnsVoidSize; private const int NullableContextSize = 3; + private const int NullableContextMask = (1 << NullableContextSize) - 1; private const int IsNullableAnalysisEnabledOffset = NullableContextOffset + NullableContextSize; -#pragma warning disable IDE0051 // Remove unused private members private const int IsNullableAnalysisEnabledSize = 1; -#pragma warning restore IDE0051 // Remove unused private members - private const int MethodKindMask = (1 << MethodKindSize) - 1; + private const int IsExpressionBodiedOffset = IsNullableAnalysisEnabledOffset + IsNullableAnalysisEnabledSize; + private const int IsExpressionBodiedSize = 1; + + private const int HasAnyBodyOffset = IsExpressionBodiedOffset + IsExpressionBodiedSize; + private const int HasAnyBodySize = 1; + private const int IsVarArgOffset = HasAnyBodyOffset + HasAnyBodySize; +#pragma warning disable IDE0051 // Remove unused private members + private const int IsVarArgSize = 1; +#pragma warning restore IDE0051 // Remove unused private members + + private const int HasAnyBodyBit = 1 << HasAnyBodyOffset; + private const int IsExpressionBodiedBit = 1 << IsExpressionBodiedOffset; private const int IsExtensionMethodBit = 1 << IsExtensionMethodOffset; private const int IsMetadataVirtualIgnoringInterfaceChangesBit = 1 << IsMetadataVirtualIgnoringInterfaceChangesOffset; private const int IsMetadataVirtualBit = 1 << IsMetadataVirtualIgnoringInterfaceChangesOffset; private const int IsMetadataVirtualLockedBit = 1 << IsMetadataVirtualLockedOffset; + private const int IsVarArgBit = 1 << IsVarArgOffset; private const int ReturnsVoidBit = 1 << ReturnsVoidOffset; private const int ReturnsVoidIsSetBit = 1 << ReturnsVoidOffset + 1; - private const int NullableContextMask = (1 << NullableContextSize) - 1; - private const int IsNullableAnalysisEnabledBit = 1 << IsNullableAnalysisEnabledOffset; public bool TryGetReturnsVoid(out bool value) @@ -93,9 +111,25 @@ public MethodKind MethodKind get { return (MethodKind)((_flags >> MethodKindOffset) & MethodKindMask); } } + public RefKind RefKind + { + get { return (RefKind)((_flags >> RefKindOffset) & RefKindMask); } + } + + public bool HasAnyBody + { + get { return (_flags & HasAnyBodyBit) != 0; } + } + + public bool IsExpressionBodied + { + get { return (_flags & IsExpressionBodiedBit) != 0; } + } + public bool IsExtensionMethod { get { return (_flags & IsExtensionMethodBit) != 0; } + set { ThreadSafeFlagOperations.Set(ref _flags, value ? IsExtensionMethodBit : 0); } } public bool IsNullableAnalysisEnabled @@ -108,11 +142,18 @@ public bool IsMetadataVirtualLocked get { return (_flags & IsMetadataVirtualLockedBit) != 0; } } + public bool IsVarArg + { + get { return (_flags & IsVarArgBit) != 0; } + set { ThreadSafeFlagOperations.Set(ref _flags, value ? IsVarArgBit : 0); } + } + #if DEBUG static Flags() { // Verify masks are sufficient for values. Debug.Assert(EnumUtilities.ContainsAllValues(MethodKindMask)); + Debug.Assert(EnumUtilities.ContainsAllValues(RefKindMask)); Debug.Assert(EnumUtilities.ContainsAllValues(NullableContextMask)); } #endif @@ -126,6 +167,7 @@ public Flags( MethodKind methodKind, DeclarationModifiers declarationModifiers, bool returnsVoid, + bool isExpressionBodied, bool isExtensionMethod, bool isNullableAnalysisEnabled, bool isMetadataVirtualIgnoringModifiers = false) @@ -133,12 +175,14 @@ public Flags( bool isMetadataVirtual = isMetadataVirtualIgnoringModifiers || ModifiersRequireMetadataVirtual(declarationModifiers); int methodKindInt = ((int)methodKind & MethodKindMask) << MethodKindOffset; + int isExpressionBodyInt = isExpressionBodied ? IsExpressionBodiedBit : 0; int isExtensionMethodInt = isExtensionMethod ? IsExtensionMethodBit : 0; int isNullableAnalysisEnabledInt = isNullableAnalysisEnabled ? IsNullableAnalysisEnabledBit : 0; int isMetadataVirtualIgnoringInterfaceImplementationChangesInt = isMetadataVirtual ? IsMetadataVirtualIgnoringInterfaceChangesBit : 0; int isMetadataVirtualInt = isMetadataVirtual ? IsMetadataVirtualBit : 0; _flags = methodKindInt + | isExpressionBodyInt | isExtensionMethodInt | isNullableAnalysisEnabledInt | isMetadataVirtualIgnoringInterfaceImplementationChangesInt @@ -147,6 +191,16 @@ public Flags( | ReturnsVoidIsSetBit; } + /// + /// Only allowed to be called in constructors of SourceMemberMethodSymbol (and derived constructors), so + /// does not need ThreadSafe operations. + /// + public void SetOrdinaryMethodFlags(RefKind refKind, bool hasAnyBody) + { + _flags |= ((int)refKind & RefKindMask) << RefKindOffset; + _flags |= hasAnyBody ? HasAnyBodyBit : 0; + } + public bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) { // This flag is immutable, so there's no reason to set a lock bit, as we do below. @@ -292,12 +346,13 @@ protected void MakeFlags( MethodKind methodKind, DeclarationModifiers declarationModifiers, bool returnsVoid, + bool isExpressionBodied, bool isExtensionMethod, bool isNullableAnalysisEnabled, bool isMetadataVirtualIgnoringModifiers = false) { DeclarationModifiers = declarationModifiers; - this.flags = new Flags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers); + this.flags = new Flags(methodKind, declarationModifiers, returnsVoid, isExpressionBodied, isExtensionMethod, isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers); } protected void SetReturnsVoid(bool returnsVoid) @@ -1003,7 +1058,7 @@ protected void CheckFeatureAvailabilityAndRuntimeSupport(SyntaxNode declarationS /// If the method has both block body and an expression body /// present, this is not treated as expression-bodied. /// - internal abstract bool IsExpressionBodied { get; } + internal bool IsExpressionBodied => flags.IsExpressionBodied; internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index 55127be6d829e..ed4fabc071d81 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -20,10 +20,6 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols internal sealed class SourceOrdinaryMethodSymbol : SourceOrdinaryMethodSymbolBase { private readonly TypeSymbol _explicitInterfaceType; - private readonly bool _isExpressionBodied; - private readonly bool _hasAnyBody; - private readonly RefKind _refKind; - private bool _lazyIsVararg; /// /// A collection of type parameter constraint types, populated when @@ -87,19 +83,16 @@ private SourceOrdinaryMethodSymbol( firstParam.Modifiers.Any(SyntaxKind.ThisKeyword), isReadOnly: false, hasBody: syntax.Body != null || syntax.ExpressionBody != null, + isExpressionBodied: syntax is { Body: null, ExpressionBody: not null }, isNullableAnalysisEnabled: isNullableAnalysisEnabled, - diagnostics) + diagnostics, + refKind: syntax.ReturnType.SkipScoped(out _).GetRefKindInLocalOrReturn(diagnostics)) { Debug.Assert(diagnostics.DiagnosticBag is object); _explicitInterfaceType = explicitInterfaceType; - bool hasBlockBody = syntax.Body != null; - _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; - bool hasBody = hasBlockBody || _isExpressionBodied; - _hasAnyBody = hasBody; Debug.Assert(syntax.ReturnType is not ScopedTypeSyntax); - _refKind = syntax.ReturnType.SkipScoped(out _).GetRefKindInLocalOrReturn(diagnostics); CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); @@ -140,7 +133,7 @@ protected override (TypeWithAnnotations ReturnType, ImmutableArray(); - _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); + flags.IsVarArg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); var returnTypeSyntax = syntax.ReturnType; Debug.Assert(returnTypeSyntax is not ScopedTypeSyntax); @@ -194,7 +187,7 @@ protected override (TypeWithAnnotations ReturnType, ImmutableArray declaredConstraints) { @@ -285,7 +278,7 @@ protected override MethodSymbol FindExplicitlyImplementedMethod(BindingDiagnosti protected override TypeSymbol ExplicitInterfaceType => _explicitInterfaceType; - protected override bool HasAnyBody => _hasAnyBody; + protected override bool HasAnyBody => flags.HasAnyBody; internal MethodDeclarationSyntax GetSyntax() { @@ -360,7 +353,7 @@ public override bool IsVararg get { LazyMethodChecks(); - return _lazyIsVararg; + return flags.IsVarArg; } } @@ -370,7 +363,7 @@ public override RefKind RefKind { get { - return _refKind; + return flags.RefKind; } } @@ -400,7 +393,7 @@ internal bool IsPartialDefinition { get { - return this.IsPartial && !_hasAnyBody && !HasExternModifier; + return this.IsPartial && !flags.HasAnyBody && !HasExternModifier; } } @@ -411,7 +404,7 @@ internal bool IsPartialImplementation { get { - return this.IsPartial && (_hasAnyBody || HasExternModifier); + return this.IsPartial && (flags.HasAnyBody || HasExternModifier); } } @@ -516,11 +509,6 @@ private SyntaxList AttributeDeclarationSyntaxList } } - internal override bool IsExpressionBodied - { - get { return _isExpressionBodied; } - } - protected override DeclarationModifiers MakeDeclarationModifiers(DeclarationModifiers allowedModifiers, BindingDiagnosticBag diagnostics) { var syntax = GetSyntax(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs index 9769624caabcf..298ab3c16db03 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs @@ -36,8 +36,10 @@ protected SourceOrdinaryMethodSymbolBase( bool isExtensionMethod, bool isReadOnly, bool hasBody, + bool isExpressionBodied, bool isNullableAnalysisEnabled, - BindingDiagnosticBag diagnostics) : + BindingDiagnosticBag diagnostics, + RefKind refKind = RefKind.None) : base(containingType, syntax.GetReference(), location, @@ -60,7 +62,8 @@ protected SourceOrdinaryMethodSymbolBase( bool isExplicitInterfaceImplementation = methodKind == MethodKind.ExplicitInterfaceImplementation; var isMetadataVirtualIgnoringModifiers = isExplicitInterfaceImplementation && (declarationModifiers & DeclarationModifiers.Static) == 0; - this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod: isExtensionMethod, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isMetadataVirtualIgnoringModifiers); + this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExpressionBodied: isExpressionBodied, isExtensionMethod: isExtensionMethod, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isMetadataVirtualIgnoringModifiers); + flags.SetOrdinaryMethodFlags(refKind, hasBody); _typeParameters = MakeTypeParameters(syntax, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index c1c7d572ce5d5..6ca6c0c0bc229 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -23,7 +23,6 @@ internal class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol private ImmutableArray _lazyExplicitInterfaceImplementations; private string _lazyName; private readonly bool _isAutoPropertyAccessor; - private readonly bool _isExpressionBodied; private readonly bool _usesInit; public static SourcePropertyAccessorSymbol CreateAccessorSymbol( @@ -128,9 +127,6 @@ public static SourcePropertyAccessorSymbol CreateAccessorSymbol( } #nullable disable - internal sealed override bool IsExpressionBodied - => _isExpressionBodied; - internal sealed override ImmutableArray NotNullMembers => _property.NotNullMembers.Concat(base.NotNullMembers); @@ -152,7 +148,6 @@ private SourcePropertyAccessorSymbol( { _property = property; _isAutoPropertyAccessor = false; - _isExpressionBodied = true; // The modifiers for the accessor are the same as the modifiers for the property, // minus the indexer and readonly bit @@ -161,7 +156,7 @@ private SourcePropertyAccessorSymbol( // ReturnsVoid property is overridden in this class so // returnsVoid argument to MakeFlags is ignored. bool isExplicitInterfaceImplementation = property.IsExplicitInterfaceImplementation; - this.MakeFlags(MethodKind.PropertyGet, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, + this.MakeFlags(MethodKind.PropertyGet, declarationModifiers, returnsVoid: false, isExpressionBodied: true, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isExplicitInterfaceImplementation && (declarationModifiers & DeclarationModifiers.Static) == 0); CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody: true, diagnostics: diagnostics); @@ -196,7 +191,7 @@ protected SourcePropertyAccessorSymbol( _property = property; _isAutoPropertyAccessor = isAutoPropertyAccessor; Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties"); - _isExpressionBodied = !hasBody && hasExpressionBody; + var isExpressionBodied = !hasBody && hasExpressionBody; _usesInit = usesInit; if (_usesInit) { @@ -217,7 +212,7 @@ protected SourcePropertyAccessorSymbol( // ReturnsVoid property is overridden in this class so // returnsVoid argument to MakeFlags is ignored. - this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isExplicitInterfaceImplementation && (declarationModifiers & DeclarationModifiers.Static) == 0); CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody: hasBody || hasExpressionBody || isAutoPropertyAccessor, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs index 973254524cca1..3fa2de838216b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs @@ -17,7 +17,6 @@ internal abstract class SourceUserDefinedOperatorSymbolBase : SourceOrdinaryMeth // tomat: ignoreDynamic should be true, but we don't want to introduce breaking change. See bug 605326. private const TypeCompareKind ComparisonForUserDefinedOperators = TypeCompareKind.IgnoreTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes; private readonly string _name; - private readonly bool _isExpressionBodied; #nullable enable private readonly TypeSymbol? _explicitInterfaceType; #nullable disable @@ -39,7 +38,6 @@ protected SourceUserDefinedOperatorSymbolBase( { _explicitInterfaceType = explicitInterfaceType; _name = name; - _isExpressionBodied = isExpressionBodied; this.CheckUnsafeModifier(declarationModifiers, diagnostics); @@ -47,7 +45,7 @@ protected SourceUserDefinedOperatorSymbolBase( // assume that the return type is non-void; when we do the lazy initialization // of the parameters and return type we will update the flag if necessary. - this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); if (this.ContainingType.IsInterface && !(IsAbstract || IsVirtual) && !IsExplicitInterfaceImplementation && @@ -795,11 +793,6 @@ public sealed override RefKind RefKind get { return RefKind.None; } } - internal sealed override bool IsExpressionBodied - { - get { return _isExpressionBodied; } - } - protected sealed override void CheckConstraintsForExplicitInterfaceType(ConversionsBase conversions, BindingDiagnosticBag diagnostics) { if ((object)_explicitInterfaceType != null) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedPrimaryConstructor.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedPrimaryConstructor.cs index 2703847c97b27..765999431fa70 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedPrimaryConstructor.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedPrimaryConstructor.cs @@ -30,6 +30,7 @@ public SynthesizedPrimaryConstructor( MethodKind.Constructor, containingType.IsAbstract ? DeclarationModifiers.Protected : DeclarationModifiers.Public, returnsVoid: true, + isExpressionBodied: false, isExtensionMethod: false, isNullableAnalysisEnabled: false); // IsNullableAnalysisEnabled uses containing type instead. } @@ -69,8 +70,6 @@ protected override ParameterListSyntax GetParameterList() protected override bool AllowRefOrOut => !(ContainingType is { IsRecord: true } or { IsRecordStruct: true }); - internal override bool IsExpressionBodied => false; - internal override bool IsNullableAnalysisEnabled() { return ContainingType.IsNullableEnabledForConstructorsAndInitializers(IsStatic); diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs index c497dbc226869..eb7b8ee4c95b7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs @@ -22,15 +22,13 @@ internal abstract class SynthesizedRecordOrdinaryMethod : SourceOrdinaryMethodSy protected SynthesizedRecordOrdinaryMethod(SourceMemberContainerTypeSymbol containingType, string name, bool isReadOnly, bool hasBody, int memberOffset, BindingDiagnosticBag diagnostics) : base(containingType, name, containingType.GetFirstLocation(), (CSharpSyntaxNode)containingType.SyntaxReferences[0].GetSyntax(), MethodKind.Ordinary, - isIterator: false, isExtensionMethod: false, isReadOnly: isReadOnly, hasBody: hasBody, isNullableAnalysisEnabled: false, diagnostics) + isIterator: false, isExtensionMethod: false, isReadOnly: isReadOnly, hasBody: hasBody, isExpressionBodied: false, isNullableAnalysisEnabled: false, diagnostics) { _memberOffset = memberOffset; } protected sealed override bool HasAnyBody => true; - internal sealed override bool IsExpressionBodied => false; - public sealed override bool IsImplicitlyDeclared => true; protected sealed override Location ReturnTypeLocation => GetFirstLocation(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs index e165c6b2f3da6..a1e01aa551d49 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEventAccessorSymbol.cs @@ -25,7 +25,7 @@ internal sealed class SynthesizedEventAccessorSymbol : SourceEventAccessorSymbol private readonly object _methodChecksLockObject = new object(); internal SynthesizedEventAccessorSymbol(SourceEventSymbol @event, bool isAdder, EventSymbol explicitlyImplementedEventOpt = null, string aliasQualifierOpt = null) - : base(@event, null, @event.Location, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder, isIterator: false, isNullableAnalysisEnabled: false) + : base(@event, null, @event.Location, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder, isIterator: false, isNullableAnalysisEnabled: false, isExpressionBodied: false) { } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs index 232f54a690883..5aba0636c498b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs @@ -57,6 +57,7 @@ internal SynthesizedSimpleProgramEntryPointSymbol(SourceMemberContainerTypeSymbo MethodKind.Ordinary, DeclarationModifiers.Static | DeclarationModifiers.Private | (hasAwait ? DeclarationModifiers.Async : DeclarationModifiers.None), returnsVoid: !hasAwait && !hasReturnWithExpression, + isExpressionBodied: false, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: false); @@ -198,8 +199,6 @@ protected override void MethodChecks(BindingDiagnosticBag diagnostics) { } - internal override bool IsExpressionBodied => false; - public override ImmutableArray> GetTypeParameterConstraintTypes() => ImmutableArray>.Empty;