diff --git a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs index 94d75be8c52a3..7c8842384cb5c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs +++ b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs @@ -218,6 +218,7 @@ 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 7362f09560c79..409c5e74098a2 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs @@ -50,8 +50,7 @@ protected SynthesizedMethodBaseSymbol(NamedTypeSymbol containingType, returnsVoid: baseMethod.ReturnsVoid, isExtensionMethod: false, isNullableAnalysisEnabled: false, - isMetadataVirtualIgnoringModifiers: false, - isExpressionBodied: false); + isMetadataVirtualIgnoringModifiers: false); } protected void AssignTypeMapAndTypeParameters(TypeMap typeMap, ImmutableArray typeParameters) @@ -227,5 +226,10 @@ 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 8fdcd2fbfd338..38371b2442a00 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -12,6 +12,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal sealed class SourceConstructorSymbol : SourceConstructorSymbolBase { + private readonly bool _isExpressionBodied; private readonly bool _hasThisInitializer; public static SourceConstructorSymbol CreateConstructorSymbol( @@ -34,14 +35,14 @@ private SourceConstructorSymbol( base(containingType, location, syntax, SyntaxFacts.HasYieldOperations(syntax)) { bool hasBlockBody = syntax.Body != null; - bool isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; - bool hasBody = hasBlockBody || isExpressionBodied; + _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, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); if (syntax.Identifier.ValueText != containingType.Name) { @@ -162,6 +163,14 @@ 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 cc309bcce023e..69ca26275e2ac 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventAccessorSymbol.cs @@ -4,7 +4,6 @@ #nullable disable -using System; using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -33,8 +32,7 @@ internal SourceCustomEventAccessorSymbol( syntax.Keyword.GetLocation(), explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder: syntax.Kind() == SyntaxKind.AddAccessorDeclaration, isIterator: SyntaxFacts.HasYieldOperations(syntax.Body), - isNullableAnalysisEnabled: isNullableAnalysisEnabled, - isExpressionBodied: syntax is { Body: null, ExpressionBody: not null }) + isNullableAnalysisEnabled: isNullableAnalysisEnabled) { Debug.Assert(syntax != null); Debug.Assert(syntax.Kind() == SyntaxKind.AddAccessorDeclaration || syntax.Kind() == SyntaxKind.RemoveAccessorDeclaration); @@ -93,5 +91,16 @@ 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 94a3fa6819e54..28d792d0608a1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -28,8 +28,7 @@ protected SourceDelegateMethodSymbol( : base(delegateType, syntax.GetReference(), location: syntax.Identifier.GetLocation(), isIterator: false) { _returnType = returnType; - this.MakeFlags( - methodKind, declarationModifiers, _returnType.IsVoidType(), isExpressionBodied: false, isExtensionMethod: false, isNullableAnalysisEnabled: false); + this.MakeFlags(methodKind, declarationModifiers, _returnType.IsVoidType(), isExtensionMethod: false, isNullableAnalysisEnabled: false); } internal sealed override ExecutableCodeBinder TryGetBodyBinder(BinderFactory binderFactoryOpt = null, bool ignoreAccessibility = false) => throw ExceptionUtilities.Unreachable(); @@ -177,6 +176,11 @@ 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 c2071844d64e2..26dc833d7353d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs @@ -14,6 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols internal sealed class SourceDestructorSymbol : SourceMemberMethodSymbol { private TypeWithAnnotations _lazyReturnType; + private readonly bool _isExpressionBodied; internal SourceDestructorSymbol( SourceMemberContainerTypeSymbol containingType, @@ -27,18 +28,17 @@ internal SourceDestructorSymbol( bool modifierErrors; var declarationModifiers = MakeModifiers(syntax.Modifiers, location, diagnostics, out modifierErrors); - - bool hasBlockBody = syntax.Body != null; - bool isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; - - this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); if (syntax.Identifier.ValueText != containingType.Name) { diagnostics.Add(ErrorCode.ERR_BadDestructorName, syntax.Identifier.GetLocation()); } - if (hasBlockBody || isExpressionBodied) + bool hasBlockBody = syntax.Body != null; + _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null; + + 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,6 +142,14 @@ 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 00d2c4cdd71d4..dc99d2054c40d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventAccessorSymbol.cs @@ -29,8 +29,7 @@ public SourceEventAccessorSymbol( string aliasQualifierOpt, bool isAdder, bool isIterator, - bool isNullableAnalysisEnabled, - bool isExpressionBodied) + bool isNullableAnalysisEnabled) : base(@event.containingType, syntaxReference, location, isIterator) { _event = @event; @@ -57,7 +56,6 @@ 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); @@ -248,5 +246,11 @@ 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 82008e1cb88c4..a6288faa15dd7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -24,10 +24,9 @@ protected struct Flags { // We currently pack everything into a 32 bit int with the following layout: // - // | |a|b|e|n|vvv|yy|s|r|q|z|kk|wwwww| + // | |n|vvv|yy|s|r|q|z|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.) @@ -35,20 +34,12 @@ 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 = RefKindOffset + RefKindSize; + private const int IsExtensionMethodOffset = MethodKindOffset + MethodKindSize; private const int IsExtensionMethodSize = 1; private const int IsMetadataVirtualIgnoringInterfaceChangesOffset = IsExtensionMethodOffset + IsExtensionMethodSize; @@ -65,33 +56,24 @@ 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; - private const int IsNullableAnalysisEnabledSize = 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; + private const int IsNullableAnalysisEnabledSize = 1; #pragma warning restore IDE0051 // Remove unused private members - private const int HasAnyBodyBit = 1 << HasAnyBodyOffset; - private const int IsExpressionBodiedBit = 1 << IsExpressionBodiedOffset; + private const int MethodKindMask = (1 << MethodKindSize) - 1; + 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) @@ -111,25 +93,9 @@ 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 @@ -142,18 +108,11 @@ 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 @@ -167,7 +126,6 @@ public Flags( MethodKind methodKind, DeclarationModifiers declarationModifiers, bool returnsVoid, - bool isExpressionBodied, bool isExtensionMethod, bool isNullableAnalysisEnabled, bool isMetadataVirtualIgnoringModifiers = false) @@ -175,14 +133,12 @@ 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 @@ -191,16 +147,6 @@ 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. @@ -346,13 +292,12 @@ 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, isExpressionBodied, isExtensionMethod, isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers); + this.flags = new Flags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers); } protected void SetReturnsVoid(bool returnsVoid) @@ -1058,7 +1003,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 bool IsExpressionBodied => flags.IsExpressionBodied; + internal abstract bool IsExpressionBodied { get; } 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 ed4fabc071d81..55127be6d829e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -20,6 +20,10 @@ 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 @@ -83,16 +87,19 @@ 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, - refKind: syntax.ReturnType.SkipScoped(out _).GetRefKindInLocalOrReturn(diagnostics)) + 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); @@ -133,7 +140,7 @@ protected override (TypeWithAnnotations ReturnType, ImmutableArray(); - flags.IsVarArg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); + _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); var returnTypeSyntax = syntax.ReturnType; Debug.Assert(returnTypeSyntax is not ScopedTypeSyntax); @@ -187,7 +194,7 @@ protected override (TypeWithAnnotations ReturnType, ImmutableArray declaredConstraints) { @@ -278,7 +285,7 @@ protected override MethodSymbol FindExplicitlyImplementedMethod(BindingDiagnosti protected override TypeSymbol ExplicitInterfaceType => _explicitInterfaceType; - protected override bool HasAnyBody => flags.HasAnyBody; + protected override bool HasAnyBody => _hasAnyBody; internal MethodDeclarationSyntax GetSyntax() { @@ -353,7 +360,7 @@ public override bool IsVararg get { LazyMethodChecks(); - return flags.IsVarArg; + return _lazyIsVararg; } } @@ -363,7 +370,7 @@ public override RefKind RefKind { get { - return flags.RefKind; + return _refKind; } } @@ -393,7 +400,7 @@ internal bool IsPartialDefinition { get { - return this.IsPartial && !flags.HasAnyBody && !HasExternModifier; + return this.IsPartial && !_hasAnyBody && !HasExternModifier; } } @@ -404,7 +411,7 @@ internal bool IsPartialImplementation { get { - return this.IsPartial && (flags.HasAnyBody || HasExternModifier); + return this.IsPartial && (_hasAnyBody || HasExternModifier); } } @@ -509,6 +516,11 @@ 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 298ab3c16db03..9769624caabcf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs @@ -36,10 +36,8 @@ protected SourceOrdinaryMethodSymbolBase( bool isExtensionMethod, bool isReadOnly, bool hasBody, - bool isExpressionBodied, bool isNullableAnalysisEnabled, - BindingDiagnosticBag diagnostics, - RefKind refKind = RefKind.None) : + BindingDiagnosticBag diagnostics) : base(containingType, syntax.GetReference(), location, @@ -62,8 +60,7 @@ protected SourceOrdinaryMethodSymbolBase( bool isExplicitInterfaceImplementation = methodKind == MethodKind.ExplicitInterfaceImplementation; var isMetadataVirtualIgnoringModifiers = isExplicitInterfaceImplementation && (declarationModifiers & DeclarationModifiers.Static) == 0; - this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExpressionBodied: isExpressionBodied, isExtensionMethod: isExtensionMethod, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isMetadataVirtualIgnoringModifiers); - flags.SetOrdinaryMethodFlags(refKind, hasBody); + this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod: isExtensionMethod, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isMetadataVirtualIgnoringModifiers); _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 6ca6c0c0bc229..c1c7d572ce5d5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -23,6 +23,7 @@ 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( @@ -127,6 +128,9 @@ public static SourcePropertyAccessorSymbol CreateAccessorSymbol( } #nullable disable + internal sealed override bool IsExpressionBodied + => _isExpressionBodied; + internal sealed override ImmutableArray NotNullMembers => _property.NotNullMembers.Concat(base.NotNullMembers); @@ -148,6 +152,7 @@ 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 @@ -156,7 +161,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, isExpressionBodied: true, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, + this.MakeFlags(MethodKind.PropertyGet, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isExplicitInterfaceImplementation && (declarationModifiers & DeclarationModifiers.Static) == 0); CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody: true, diagnostics: diagnostics); @@ -191,7 +196,7 @@ protected SourcePropertyAccessorSymbol( _property = property; _isAutoPropertyAccessor = isAutoPropertyAccessor; Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties"); - var isExpressionBodied = !hasBody && hasExpressionBody; + _isExpressionBodied = !hasBody && hasExpressionBody; _usesInit = usesInit; if (_usesInit) { @@ -212,7 +217,7 @@ protected SourcePropertyAccessorSymbol( // ReturnsVoid property is overridden in this class so // returnsVoid argument to MakeFlags is ignored. - this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, 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 3fa2de838216b..973254524cca1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs @@ -17,6 +17,7 @@ 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 @@ -38,6 +39,7 @@ protected SourceUserDefinedOperatorSymbolBase( { _explicitInterfaceType = explicitInterfaceType; _name = name; + _isExpressionBodied = isExpressionBodied; this.CheckUnsafeModifier(declarationModifiers, diagnostics); @@ -45,7 +47,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, isExpressionBodied: isExpressionBodied, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); + this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled); if (this.ContainingType.IsInterface && !(IsAbstract || IsVirtual) && !IsExplicitInterfaceImplementation && @@ -793,6 +795,11 @@ 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 765999431fa70..2703847c97b27 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedPrimaryConstructor.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedPrimaryConstructor.cs @@ -30,7 +30,6 @@ public SynthesizedPrimaryConstructor( MethodKind.Constructor, containingType.IsAbstract ? DeclarationModifiers.Protected : DeclarationModifiers.Public, returnsVoid: true, - isExpressionBodied: false, isExtensionMethod: false, isNullableAnalysisEnabled: false); // IsNullableAnalysisEnabled uses containing type instead. } @@ -70,6 +69,8 @@ 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 eb7b8ee4c95b7..c497dbc226869 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs @@ -22,13 +22,15 @@ 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, isExpressionBodied: false, isNullableAnalysisEnabled: false, diagnostics) + isIterator: false, isExtensionMethod: false, isReadOnly: isReadOnly, hasBody: hasBody, 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 a1e01aa551d49..e165c6b2f3da6 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, isExpressionBodied: false) + : base(@event, null, @event.Location, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder, isIterator: false, isNullableAnalysisEnabled: false) { } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs index 5aba0636c498b..232f54a690883 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs @@ -57,7 +57,6 @@ 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); @@ -199,6 +198,8 @@ protected override void MethodChecks(BindingDiagnosticBag diagnostics) { } + internal override bool IsExpressionBodied => false; + public override ImmutableArray> GetTypeParameterConstraintTypes() => ImmutableArray>.Empty;