From 35ff572544c3f4a77f8651b3801a65cd303c3254 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Wed, 27 Jul 2022 21:51:10 -0700 Subject: [PATCH 1/3] Rename LifetimeAnnotationAttribute to ScopedRefAttribute and simplify --- .../Portable/BoundTree/UnboundLambda.cs | 2 +- .../Emitter/Model/PEAssemblyBuilder.cs | 29 +-- .../Portable/Emitter/Model/PEModuleBuilder.cs | 18 +- .../SynthesizedClosureMethod.cs | 2 +- .../Symbols/Compilation_WellKnownMembers.cs | 15 +- .../Portable/Symbols/DeclarationScope.cs | 2 +- .../Portable/Symbols/EmbeddableAttributes.cs | 2 +- .../Symbols/Metadata/PE/PEParameterSymbol.cs | 34 +-- .../Symbols/Source/LocalFunctionSymbol.cs | 2 +- .../Symbols/Source/ParameterHelpers.cs | 18 +- .../Source/SourceConstructorSymbolBase.cs | 2 +- .../Source/SourceDelegateMethodSymbol.cs | 2 +- ...dinaryMethodOrUserDefinedOperatorSymbol.cs | 2 +- .../Source/SourceParameterSymbolBase.cs | 4 +- .../Source/SourcePropertySymbolBase.cs | 2 +- ...beddedLifetimeAnnotationAttributeSymbol.cs | 34 +-- .../Synthesized/SynthesizedParameterSymbol.cs | 4 +- .../AttributeTests_LifetimeAnnotation.cs | 239 +++++++++--------- .../Test/Semantic/Semantics/RefFieldTests.cs | 58 +---- .../Symbol/Symbols/MissingSpecialMember.cs | 4 +- .../Core/Portable/MetadataReader/PEModule.cs | 11 +- .../Attributes/AttributeDescription.cs | 4 +- .../Core/Portable/WellKnownMember.cs | 2 +- .../Core/Portable/WellKnownMembers.cs | 8 +- src/Compilers/Core/Portable/WellKnownTypes.cs | 4 +- .../LifetimeAnnotationAttributesVisitor.cs | 16 +- .../WellKnownTypeValidationTests.vb | 8 +- 27 files changed, 216 insertions(+), 312 deletions(-) diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index cc19e25919b24..b8a6a9f4e9798 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -744,7 +744,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType, bool inExpressionTr } ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, lambdaParameters, diagnostics, modifyCompilation: false); - ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, lambdaParameters, diagnostics, modifyCompilation: false); + ParameterHelpers.EnsureScopedRefAttributeExists(compilation, lambdaParameters, diagnostics, modifyCompilation: false); ParameterHelpers.EnsureNullableAttributeExists(compilation, lambdaSymbol, lambdaParameters, diagnostics, modifyCompilation: false); // Note: we don't need to warn on annotations used in #nullable disable context for lambdas, as this is handled in binding already diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs index ee7e7fa30cdbf..0730e502562b9 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs @@ -40,7 +40,7 @@ internal abstract class PEAssemblyBuilderBase : PEModuleBuilder, Cci.IAssemblyRe private SynthesizedEmbeddedNullableContextAttributeSymbol _lazyNullableContextAttribute; private SynthesizedEmbeddedNullablePublicOnlyAttributeSymbol _lazyNullablePublicOnlyAttribute; private SynthesizedEmbeddedNativeIntegerAttributeSymbol _lazyNativeIntegerAttribute; - private SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol _lazyLifetimeAnnotationAttribute; + private SynthesizedEmbeddedScopedRefAttributeSymbol _lazyScopedRefAttribute; /// /// The behavior of the C# command-line compiler is as follows: @@ -99,7 +99,7 @@ internal sealed override ImmutableArray GetEmbeddedTypes(Bindin builder.AddIfNotNull(_lazyNullableContextAttribute); builder.AddIfNotNull(_lazyNullablePublicOnlyAttribute); builder.AddIfNotNull(_lazyNativeIntegerAttribute); - builder.AddIfNotNull(_lazyLifetimeAnnotationAttribute); + builder.AddIfNotNull(_lazyScopedRefAttribute); return builder.ToImmutableAndFree(); } @@ -251,17 +251,17 @@ internal override SynthesizedAttributeData SynthesizeNativeIntegerAttribute(Well return base.SynthesizeNativeIntegerAttribute(member, arguments); } - internal override SynthesizedAttributeData SynthesizeLifetimeAnnotationAttribute(WellKnownMember member, ImmutableArray arguments) + internal override SynthesizedAttributeData SynthesizeScopedRefAttribute(WellKnownMember member) { - if ((object)_lazyLifetimeAnnotationAttribute != null) + if ((object)_lazyScopedRefAttribute != null) { return new SynthesizedAttributeData( - _lazyLifetimeAnnotationAttribute.Constructors[0], - arguments, + _lazyScopedRefAttribute.Constructors[0], + ImmutableArray.Empty, ImmutableArray>.Empty); } - return base.SynthesizeLifetimeAnnotationAttribute(member, arguments); + return base.SynthesizeScopedRefAttribute(member); } protected override SynthesizedAttributeData TrySynthesizeIsReadOnlyAttribute() @@ -389,13 +389,13 @@ private void CreateEmbeddedAttributesIfNeeded(BindingDiagnosticBag diagnostics) CreateNativeIntegerAttributeSymbol); } - if ((needsAttributes & EmbeddableAttributes.LifetimeAnnotationAttribute) != 0) + if ((needsAttributes & EmbeddableAttributes.ScopedRefAttribute) != 0) { CreateAttributeIfNeeded( - ref _lazyLifetimeAnnotationAttribute, + ref _lazyScopedRefAttribute, diagnostics, - AttributeDescription.LifetimeAnnotationAttribute, - CreateLifetimeAnnotationAttributeSymbol); + AttributeDescription.ScopedRefAttribute, + CreateScopedRefAttributeSymbol); } } @@ -438,13 +438,12 @@ private SynthesizedEmbeddedNativeIntegerAttributeSymbol CreateNativeIntegerAttri GetWellKnownType(WellKnownType.System_Attribute, diagnostics), GetSpecialType(SpecialType.System_Boolean, diagnostics)); - private SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol CreateLifetimeAnnotationAttributeSymbol(string name, NamespaceSymbol containingNamespace, BindingDiagnosticBag diagnostics) - => new SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol( + private SynthesizedEmbeddedScopedRefAttributeSymbol CreateScopedRefAttributeSymbol(string name, NamespaceSymbol containingNamespace, BindingDiagnosticBag diagnostics) + => new SynthesizedEmbeddedScopedRefAttributeSymbol( name, containingNamespace, SourceModule, - GetWellKnownType(WellKnownType.System_Attribute, diagnostics), - GetSpecialType(SpecialType.System_Boolean, diagnostics)); + GetWellKnownType(WellKnownType.System_Attribute, diagnostics)); private void CreateAttributeIfNeeded( ref T symbol, diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 13803de6d1fff..81617bf79940f 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -1710,7 +1710,7 @@ internal virtual SynthesizedAttributeData SynthesizeNativeIntegerAttribute(WellK return Compilation.TrySynthesizeAttribute(member, arguments, isOptionalUse: true); } - internal SynthesizedAttributeData SynthesizeLifetimeAnnotationAttribute(ParameterSymbol symbol, DeclarationScope scope) + internal SynthesizedAttributeData SynthesizeScopedRefAttribute(ParameterSymbol symbol, DeclarationScope scope) { Debug.Assert(scope != DeclarationScope.Unscoped); Debug.Assert(symbol.RefKind != RefKind.Out || scope == DeclarationScope.ValueScoped); @@ -1722,20 +1722,14 @@ internal SynthesizedAttributeData SynthesizeLifetimeAnnotationAttribute(Paramete return null; } - var booleanType = Compilation.GetSpecialType(SpecialType.System_Boolean); - Debug.Assert((object)booleanType != null); - return SynthesizeLifetimeAnnotationAttribute( - WellKnownMember.System_Runtime_CompilerServices_LifetimeAnnotationAttribute__ctor, - ImmutableArray.Create( - new TypedConstant(booleanType, TypedConstantKind.Primitive, scope == DeclarationScope.RefScoped), - new TypedConstant(booleanType, TypedConstantKind.Primitive, scope == DeclarationScope.ValueScoped))); + return SynthesizeScopedRefAttribute(WellKnownMember.System_Runtime_CompilerServices_ScopedRefAttribute__ctor); } - internal virtual SynthesizedAttributeData SynthesizeLifetimeAnnotationAttribute(WellKnownMember member, ImmutableArray arguments) + internal virtual SynthesizedAttributeData SynthesizeScopedRefAttribute(WellKnownMember member) { // For modules, this attribute should be present. Only assemblies generate and embed this type. // https://github.com/dotnet/roslyn/issues/30062 Should not be optional. - return Compilation.TrySynthesizeAttribute(member, arguments, isOptionalUse: true); + return Compilation.TrySynthesizeAttribute(member, isOptionalUse: true); } internal bool ShouldEmitNullablePublicOnlyAttribute() @@ -1811,9 +1805,9 @@ internal void EnsureNativeIntegerAttributeExists() EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute); } - internal void EnsureLifetimeAnnotationAttributeExists() + internal void EnsureScopedRefAttributeExists() { - EnsureEmbeddableAttributeExists(EmbeddableAttributes.LifetimeAnnotationAttribute); + EnsureEmbeddableAttributeExists(EmbeddableAttributes.ScopedRefAttribute); } #nullable enable diff --git a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs index fb56339d1b7a1..a4a60a68dcb90 100644 --- a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs +++ b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/SynthesizedClosureMethod.cs @@ -134,7 +134,7 @@ private void EnsureAttributesExist(TypeCompilationState compilationState) ParameterHelpers.EnsureNativeIntegerAttributeExists(moduleBuilder, Parameters); } - ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(moduleBuilder, Parameters); + ParameterHelpers.EnsureScopedRefAttributeExists(moduleBuilder, Parameters); if (compilationState.Compilation.ShouldEmitNullableAttributes(this)) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs index a1cd90db4c825..49576857a007d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs @@ -388,8 +388,7 @@ internal override ITypeSymbolInternal CommonGetWellKnownType(WellKnownType wellk ImmutableArray> namedArguments = default, bool isOptionalUse = false) { - UseSiteInfo info; - var ctorSymbol = (MethodSymbol)Binder.GetWellKnownTypeMember(this, constructor, out info, isOptional: true); + var ctorSymbol = (MethodSymbol)Binder.GetWellKnownTypeMember(this, constructor, useSiteInfo: out _, isOptional: true); if ((object)ctorSymbol == null) { @@ -413,7 +412,7 @@ internal override ITypeSymbolInternal CommonGetWellKnownType(WellKnownType wellk var builder = new ArrayBuilder>(namedArguments.Length); foreach (var arg in namedArguments) { - var wellKnownMember = Binder.GetWellKnownTypeMember(this, arg.Key, out info, isOptional: true); + var wellKnownMember = Binder.GetWellKnownTypeMember(this, arg.Key, useSiteInfo: out _, isOptional: true); if (wellKnownMember == null || wellKnownMember is ErrorTypeSymbol) { // if this assert fails, UseSiteErrors for "member" have not been checked before emitting ... @@ -544,9 +543,9 @@ internal void EnsureNativeIntegerAttributeExists(BindingDiagnosticBag? diagnosti EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute, diagnostics, location, modifyCompilation); } - internal void EnsureLifetimeAnnotationAttributeExists(BindingDiagnosticBag? diagnostics, Location location, bool modifyCompilation) + internal void EnsureScopedRefAttributeExists(BindingDiagnosticBag? diagnostics, Location location, bool modifyCompilation) { - EnsureEmbeddableAttributeExists(EmbeddableAttributes.LifetimeAnnotationAttribute, diagnostics, location, modifyCompilation); + EnsureEmbeddableAttributeExists(EmbeddableAttributes.ScopedRefAttribute, diagnostics, location, modifyCompilation); } internal bool CheckIfAttributeShouldBeEmbedded(EmbeddableAttributes attribute, BindingDiagnosticBag? diagnosticsOpt, Location locationOpt) @@ -607,12 +606,12 @@ internal bool CheckIfAttributeShouldBeEmbedded(EmbeddableAttributes attribute, B WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor, WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags); - case EmbeddableAttributes.LifetimeAnnotationAttribute: + case EmbeddableAttributes.ScopedRefAttribute: return CheckIfAttributeShouldBeEmbedded( diagnosticsOpt, locationOpt, - WellKnownType.System_Runtime_CompilerServices_LifetimeAnnotationAttribute, - WellKnownMember.System_Runtime_CompilerServices_LifetimeAnnotationAttribute__ctor); + WellKnownType.System_Runtime_CompilerServices_ScopedRefAttribute, + WellKnownMember.System_Runtime_CompilerServices_ScopedRefAttribute__ctor); default: throw ExceptionUtilities.UnexpectedValue(attribute); diff --git a/src/Compilers/CSharp/Portable/Symbols/DeclarationScope.cs b/src/Compilers/CSharp/Portable/Symbols/DeclarationScope.cs index 1aaa271c757ce..4f810253cade2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/DeclarationScope.cs +++ b/src/Compilers/CSharp/Portable/Symbols/DeclarationScope.cs @@ -6,7 +6,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { // https://github.com/dotnet/roslyn/issues/61647: Internally, scope is represented with this enum, // but the public API uses a pair of IsRefScoped and IsValueScoped bools (see ILocalSymbol, - // IParameterSymbol, and LifetimeAnnotationAttribute). We should have a common representation. + // IParameterSymbol, and ScopedRefAttribute). We should have a common representation. // And we should use common terms for the attribute and enum names. internal enum DeclarationScope : byte { diff --git a/src/Compilers/CSharp/Portable/Symbols/EmbeddableAttributes.cs b/src/Compilers/CSharp/Portable/Symbols/EmbeddableAttributes.cs index 7b90cb00b6461..d50efa69a818e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/EmbeddableAttributes.cs +++ b/src/Compilers/CSharp/Portable/Symbols/EmbeddableAttributes.cs @@ -16,6 +16,6 @@ internal enum EmbeddableAttributes NullableContextAttribute = 0x10, NullablePublicOnlyAttribute = 0x20, NativeIntegerAttribute = 0x40, - LifetimeAnnotationAttribute = 0x80, + ScopedRefAttribute = 0x80, } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs index 7bf85f26e74f1..f80f17b66eb05 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs @@ -270,7 +270,6 @@ private PEParameterSymbol( if (inOutFlags == ParameterAttributes.Out) { refKind = RefKind.Out; - scope = DeclarationScope.RefScoped; } else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle)) { @@ -294,16 +293,27 @@ private PEParameterSymbol( typeWithAnnotations = NullableTypeDecoder.TransformType(typeWithAnnotations, handle, moduleSymbol, accessSymbol: accessSymbol, nullableContext: nullableContext); typeWithAnnotations = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithAnnotations, handle, moduleSymbol); - if (_moduleSymbol.Module.HasLifetimeAnnotationAttribute(_handle, out var pair)) + if (refKind == RefKind.Out) + { + scope = DeclarationScope.RefScoped; + } + else if (_moduleSymbol.Module.HasScopedRefAttribute(_handle)) { - var scopeOpt = GetScope(refKind, typeWithAnnotations.Type, pair.IsRefScoped, pair.IsValueScoped); - if (scopeOpt is null) + if (isByRef) { - isBad = true; + Debug.Assert(refKind != RefKind.None); + scope = DeclarationScope.RefScoped; } else { - scope = scopeOpt.GetValueOrDefault(); + if (typeWithAnnotations.Type.IsRefLikeType) + { + scope = DeclarationScope.ValueScoped; + } + else + { + isBad = true; + } } } } @@ -980,16 +990,6 @@ public override ImmutableArray DeclaringSyntaxReferences internal sealed override DeclarationScope Scope => _packedFlags.Scope; - private static DeclarationScope? GetScope(RefKind refKind, TypeSymbol type, bool isRefScoped, bool isValueScoped) - { - return (isRefScoped, isValueScoped) switch - { - (false, false) => DeclarationScope.Unscoped, - (true, false) => refKind != RefKind.None ? DeclarationScope.RefScoped : null, - (_, true) => type.IsRefLikeType ? DeclarationScope.ValueScoped : null, - }; - } - public override ImmutableArray GetAttributes() { if (_lazyCustomAttributes.IsDefault) @@ -1031,7 +1031,7 @@ public override ImmutableArray GetAttributes() out _, filterIsReadOnlyAttribute ? AttributeDescription.IsReadOnlyAttribute : default, out _, - AttributeDescription.LifetimeAnnotationAttribute, + AttributeDescription.ScopedRefAttribute, out _, default); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs index 6efcfb471c5d8..4867c9244a389 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs @@ -195,7 +195,7 @@ private void ComputeParameters() var compilation = DeclaringCompilation; ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false); ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false); - ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false); + ParameterHelpers.EnsureScopedRefAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false); ParameterHelpers.EnsureNullableAttributeExists(compilation, this, parameters, diagnostics, modifyCompilation: false); // Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs index 6ee4c2db96bac..b00972c7de297 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs @@ -306,7 +306,7 @@ private static void EnsureNativeIntegerAttributeExists(CSharpCompilation compila } } - internal static bool RequiresLifetimeAnnotationAttribute(ParameterSymbol parameter) + internal static bool RequiresScopedRefAttribute(ParameterSymbol parameter) { Debug.Assert(!parameter.IsThis); @@ -322,12 +322,12 @@ internal static bool RequiresLifetimeAnnotationAttribute(ParameterSymbol paramet return true; } - internal static void EnsureLifetimeAnnotationAttributeExists(PEModuleBuilder moduleBuilder, ImmutableArray parameters) + internal static void EnsureScopedRefAttributeExists(PEModuleBuilder moduleBuilder, ImmutableArray parameters) { - EnsureLifetimeAnnotationAttributeExists(moduleBuilder.Compilation, parameters, diagnostics: null, modifyCompilation: false, moduleBuilder); + EnsureScopedRefAttributeExists(moduleBuilder.Compilation, parameters, diagnostics: null, modifyCompilation: false, moduleBuilder); } - internal static void EnsureLifetimeAnnotationAttributeExists(CSharpCompilation? compilation, ImmutableArray parameters, BindingDiagnosticBag diagnostics, bool modifyCompilation) + internal static void EnsureScopedRefAttributeExists(CSharpCompilation? compilation, ImmutableArray parameters, BindingDiagnosticBag diagnostics, bool modifyCompilation) { // These parameters might not come from a compilation (example: lambdas evaluated in EE). // During rewriting, lowering will take care of flagging the appropriate PEModuleBuilder instead. @@ -336,22 +336,22 @@ internal static void EnsureLifetimeAnnotationAttributeExists(CSharpCompilation? return; } - EnsureLifetimeAnnotationAttributeExists(compilation, parameters, diagnostics, modifyCompilation, moduleBuilder: null); + EnsureScopedRefAttributeExists(compilation, parameters, diagnostics, modifyCompilation, moduleBuilder: null); } - private static void EnsureLifetimeAnnotationAttributeExists(CSharpCompilation compilation, ImmutableArray parameters, BindingDiagnosticBag? diagnostics, bool modifyCompilation, PEModuleBuilder? moduleBuilder) + private static void EnsureScopedRefAttributeExists(CSharpCompilation compilation, ImmutableArray parameters, BindingDiagnosticBag? diagnostics, bool modifyCompilation, PEModuleBuilder? moduleBuilder) { foreach (var parameter in parameters) { - if (RequiresLifetimeAnnotationAttribute(parameter)) + if (RequiresScopedRefAttribute(parameter)) { if (moduleBuilder is { }) { - moduleBuilder.EnsureLifetimeAnnotationAttributeExists(); + moduleBuilder.EnsureScopedRefAttributeExists(); } else { - compilation.EnsureLifetimeAnnotationAttributeExists(diagnostics, GetParameterLocation(parameter), modifyCompilation); + compilation.EnsureScopedRefAttributeExists(diagnostics, GetParameterLocation(parameter), modifyCompilation); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs index 49d06f3996bf4..20673caf3d46e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs @@ -94,7 +94,7 @@ internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conve var compilation = DeclaringCompilation; ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); - ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); + ParameterHelpers.EnsureScopedRefAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true); foreach (var parameter in this.Parameters) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs index d5a9dbde6cf71..f24beead08d5d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -340,7 +340,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, } ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); - ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); + ParameterHelpers.EnsureScopedRefAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute()) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodOrUserDefinedOperatorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodOrUserDefinedOperatorSymbol.cs index c952b7a10b125..32847d1f0f362 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodOrUserDefinedOperatorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodOrUserDefinedOperatorSymbol.cs @@ -261,7 +261,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); - ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); + ParameterHelpers.EnsureScopedRefAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute()) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs index 96700c3745f60..9ada805de7ade 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs @@ -99,9 +99,9 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type)); } - if (ParameterHelpers.RequiresLifetimeAnnotationAttribute(this)) + if (ParameterHelpers.RequiresScopedRefAttribute(this)) { - AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, Scope)); + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeScopedRefAttribute(this, Scope)); } if (type.Type.ContainsTupleNames()) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index f597228d91dec..9b9a73fc39f4d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -835,7 +835,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); - ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); + ParameterHelpers.EnsureScopedRefAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNullableAttributes(this) && this.TypeWithAnnotations.NeedsNullableAttribute()) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs index 3214a32987e8b..fed825aa6af63 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs @@ -10,51 +10,27 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { - internal sealed class SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol : SynthesizedEmbeddedAttributeSymbolBase + internal sealed class SynthesizedEmbeddedScopedRefAttributeSymbol : SynthesizedEmbeddedAttributeSymbolBase { - private readonly ImmutableArray _fields; private readonly ImmutableArray _constructors; - public SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol( + public SynthesizedEmbeddedScopedRefAttributeSymbol( string name, NamespaceSymbol containingNamespace, ModuleSymbol containingModule, - NamedTypeSymbol systemAttributeType, - TypeSymbol boolType) + NamedTypeSymbol systemAttributeType) : base(name, containingNamespace, containingModule, baseType: systemAttributeType) { - _fields = ImmutableArray.Create( - new SynthesizedFieldSymbol(this, boolType, "IsRefScoped", isPublic: true, isReadOnly: true, isStatic: false), - new SynthesizedFieldSymbol(this, boolType, "IsValueScoped", isPublic: true, isReadOnly: true, isStatic: false)); - _constructors = ImmutableArray.Create( new SynthesizedEmbeddedAttributeConstructorWithBodySymbol( this, - m => ImmutableArray.Create( - SynthesizedParameterSymbol.Create(m, TypeWithAnnotations.Create(boolType), 0, RefKind.None), - SynthesizedParameterSymbol.Create(m, TypeWithAnnotations.Create(boolType), 1, RefKind.None)), - (f, s, p) => GenerateConstructorBody(f, s, p))); + getParameters: m => ImmutableArray.Empty, + getConstructorBody: (f, s, p) => { })); } - internal override IEnumerable GetFieldsToEmit() => _fields; - public override ImmutableArray Constructors => _constructors; internal override AttributeUsageInfo GetAttributeUsageInfo() => new AttributeUsageInfo(AttributeTargets.Parameter, allowMultiple: false, inherited: false); - - private void GenerateConstructorBody(SyntheticBoundNodeFactory factory, ArrayBuilder statements, ImmutableArray parameters) - { - statements.Add( - factory.ExpressionStatement( - factory.AssignmentExpression( - factory.Field(factory.This(), _fields[0]), - factory.Parameter(parameters[0])))); - statements.Add( - factory.ExpressionStatement( - factory.AssignmentExpression( - factory.Field(factory.This(), _fields[1]), - factory.Parameter(parameters[1])))); - } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs index 79a23c89a71fc..cbd6796524734 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs @@ -160,9 +160,9 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type)); } - if (ParameterHelpers.RequiresLifetimeAnnotationAttribute(this)) + if (ParameterHelpers.RequiresScopedRefAttribute(this)) { - AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, Scope)); + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeScopedRefAttribute(this, Scope)); } if (type.Type.ContainsTupleNames() && diff --git a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs index 59bb3ecc163d4..d017899380245 100644 --- a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs +++ b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs @@ -17,21 +17,14 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { - public class AttributeTests_LifetimeAnnotation : CSharpTestBase + public class AttributeTests_ScopedRef : CSharpTestBase { - private const string LifetimeAnnotationAttributeDefinition = + private const string ScopedRefAttributeDefinition = @"namespace System.Runtime.CompilerServices { - [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)] - public sealed class LifetimeAnnotationAttribute : Attribute + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + public sealed class ScopedRefAttribute : Attribute { - public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped) - { - IsRefScoped = isRefScoped; - IsValueScoped = isValueScoped; - } - public bool IsRefScoped { get; } - public bool IsValueScoped { get; } } }"; @@ -43,22 +36,22 @@ public void ExplicitAttribute_FromSource() { public static void F(scoped ref int i) { } }"; - var comp = CreateCompilation(new[] { LifetimeAnnotationAttributeDefinition, source }); + var comp = CreateCompilation(new[] { ScopedRefAttributeDefinition, source }); var expected = @" void Program.F(ref System.Int32 i) - [LifetimeAnnotation(True, False)] ref System.Int32 i + [ScopedRef] ref System.Int32 i "; CompileAndVerify(comp, symbolValidator: module => { - Assert.Equal("System.Runtime.CompilerServices.LifetimeAnnotationAttribute", GetLifetimeAnnotationType(module).ToTestDisplayString()); - AssertLifetimeAnnotationAttributes(module, expected); + Assert.Equal("System.Runtime.CompilerServices.ScopedRefAttribute", GetScopedRefType(module).ToTestDisplayString()); + AssertScopedRefAttributes(module, expected); }); } [Fact] public void ExplicitAttribute_FromMetadata() { - var comp = CreateCompilation(LifetimeAnnotationAttributeDefinition); + var comp = CreateCompilation(ScopedRefAttributeDefinition); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); @@ -70,56 +63,31 @@ public static void F(scoped ref int i) { } comp = CreateCompilation(source, references: new[] { ref0 }); var expected = @"void Program.F(ref System.Int32 i) - [LifetimeAnnotation(True, False)] ref System.Int32 i + [ScopedRef] ref System.Int32 i "; CompileAndVerify(comp, symbolValidator: module => { - Assert.Null(GetLifetimeAnnotationType(module)); - AssertLifetimeAnnotationAttributes(module, expected); + Assert.Null(GetScopedRefType(module)); + AssertScopedRefAttributes(module, expected); }); } - [Fact] - public void ExplicitAttribute_MissingConstructor() - { - var source1 = -@"namespace System.Runtime.CompilerServices -{ - public sealed class LifetimeAnnotationAttribute : Attribute - { - public LifetimeAnnotationAttribute() { } - public bool IsRefScoped { get; } - public bool IsValueScoped { get; } - } -}"; - var source2 = -@"class Program -{ - public static void F(scoped ref int i) { } -}"; - var comp = CreateCompilation(new[] { source1, source2 }); - comp.VerifyEmitDiagnostics( - // (3,26): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.LifetimeAnnotationAttribute..ctor' - // public static void F(scoped ref int i) { } - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "scoped ref int i").WithArguments("System.Runtime.CompilerServices.LifetimeAnnotationAttribute", ".ctor").WithLocation(3, 26)); - } - [WorkItem(62124, "https://github.com/dotnet/roslyn/issues/62124")] [Fact] public void ExplicitAttribute_ReferencedInSource_01() { var source = @"using System.Runtime.CompilerServices; -delegate void D([LifetimeAnnotation(true, false)] ref int i); +delegate void D([ScopedRef] ref int i); class Program { - public static void Main([LifetimeAnnotation(false, true)] string[] args) + public static void Main([ScopedRef] string[] args) { - D d = ([LifetimeAnnotation(true, false)] ref int i) => { }; + D d = ([ScopedRef] ref int i) => { }; } }"; - var comp = CreateCompilation(new[] { LifetimeAnnotationAttributeDefinition, source }); - // https://github.com/dotnet/roslyn/issues/62124: Re-enable check for LifetimeAnnotationAttribute in ReportExplicitUseOfReservedAttributes. + var comp = CreateCompilation(new[] { ScopedRefAttributeDefinition, source }); + // https://github.com/dotnet/roslyn/issues/62124: Re-enable check for ScopedRefAttribute in ReportExplicitUseOfReservedAttributes. comp.VerifyDiagnostics(); } @@ -130,34 +98,58 @@ public void ExplicitAttribute_ReferencedInSource_02() var source = @"using System; using System.Runtime.CompilerServices; -[module: LifetimeAnnotation(false, true)] -[LifetimeAnnotation(false, true)] class Program +[module: ScopedRef] +[ScopedRef] class Program { - [LifetimeAnnotation(false, true)] object F; - [LifetimeAnnotation(false, true)] event EventHandler E; - [LifetimeAnnotation(false, true)] object P { get; } - [LifetimeAnnotation(false, true)] static object M1() => throw null; - [return: LifetimeAnnotation(false, true)] static object M2() => throw null; - static void M3<[LifetimeAnnotation(false, true)] T>() { } + [ScopedRef] object F; + [ScopedRef] event EventHandler E; + [ScopedRef] object P { get; } + [ScopedRef] static object M1() => throw null; + [ScopedRef] static object M2() => throw null; + static void M3<[ScopedRef] T>() { } }"; - var comp = CreateCompilation(new[] { LifetimeAnnotationAttributeDefinition, source }); - // https://github.com/dotnet/roslyn/issues/62124: Re-enable check for LifetimeAnnotationAttribute in ReportExplicitUseOfReservedAttributes. + var comp = CreateCompilation(new[] { ScopedRefAttributeDefinition, source }); + // https://github.com/dotnet/roslyn/issues/62124: Re-enable check for ScopedRefAttribute in ReportExplicitUseOfReservedAttributes. comp.VerifyDiagnostics( - // (6,46): warning CS0169: The field 'Program.F' is never used - // [LifetimeAnnotation(false, true)] object F; - Diagnostic(ErrorCode.WRN_UnreferencedField, "F").WithArguments("Program.F").WithLocation(6, 46), - // (7,58): warning CS0067: The event 'Program.E' is never used - // [LifetimeAnnotation(false, true)] event EventHandler E; - Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("Program.E").WithLocation(7, 58)); + // (3,10): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // [module: ScopedRef] + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(3, 10), + // (4,2): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // [ScopedRef] class Program + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(4, 2), + // (6,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // [ScopedRef] object F; + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(6, 6), + // (6,24): warning CS0169: The field 'Program.F' is never used + // [ScopedRef] object F; + Diagnostic(ErrorCode.WRN_UnreferencedField, "F").WithArguments("Program.F").WithLocation(6, 24), + // (7,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // [ScopedRef] event EventHandler E; + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(7, 6), + // (7,36): warning CS0067: The event 'Program.E' is never used + // [ScopedRef] event EventHandler E; + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("Program.E").WithLocation(7, 36), + // (8,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // [ScopedRef] object P { get; } + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(8, 6), + // (9,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // [ScopedRef] static object M1() => throw null; + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(9, 6), + // (10,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // [ScopedRef] static object M2() => throw null; + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(10, 6), + // (11,21): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. + // static void M3<[ScopedRef] T>() { } + Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(11, 21)); } [Fact] public void ExplicitAttribute_UnexpectedParameterTargets() { var source0 = -@".class private System.Runtime.CompilerServices.LifetimeAnnotationAttribute extends [mscorlib]System.Attribute +@".class private System.Runtime.CompilerServices.ScopedRefAttribute extends [mscorlib]System.Attribute { - .method public hidebysig specialname rtspecialname instance void .ctor(bool isRefScoped, bool isValueScoped) cil managed { ret } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } .class public sealed R extends [mscorlib]System.ValueType { @@ -169,25 +161,25 @@ .class public A .method public static void F1(valuetype R r) { .param [1] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor(bool, bool) = ( 01 00 01 00 00 00 ) // LifetimeAnnotationAttribute(isRefScoped: true, isValueScoped: false) + .custom instance void System.Runtime.CompilerServices.ScopedRefAttribute::.ctor() = ( 01 00 00 00 ) // ScopedRefAttribute() ret } .method public static void F2(int32 y) { .param [1] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor(bool, bool) = ( 01 00 00 01 00 00 ) // LifetimeAnnotationAttribute(isRefScoped: false, isValueScoped: true) + .custom instance void System.Runtime.CompilerServices.ScopedRefAttribute::.ctor() = ( 01 00 00 00 ) // ScopedRefAttribute() ret } .method public static void F3(object x, int32& y) { .param [2] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor(bool, bool) = ( 01 00 00 01 00 00 ) // LifetimeAnnotationAttribute(isRefScoped: false, isValueScoped: true) + .custom instance void System.Runtime.CompilerServices.ScopedRefAttribute::.ctor() = ( 01 00 00 00 ) // ScopedRefAttribute() ret } .method public static void F4(valuetype R& r) { .param [1] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor(bool, bool) = ( 01 00 01 01 00 00 ) // LifetimeAnnotationAttribute(isRefScoped: true, isValueScoped: true) + .custom instance void System.Runtime.CompilerServices.ScopedRefAttribute::.ctor() = ( 01 00 00 00 ) // ScopedRefAttribute() ret } } @@ -210,29 +202,33 @@ static void Main() }"; var comp = CreateCompilation(source1, references: new[] { ref0 }); comp.VerifyDiagnostics( - // (6,11): error CS0570: 'A.F1(R)' is not supported by the language - // A.F1(r); - Diagnostic(ErrorCode.ERR_BindToBogus, "F1").WithArguments("A.F1(R)").WithLocation(6, 11), // (7,11): error CS0570: 'A.F2(int)' is not supported by the language // A.F2(2); - Diagnostic(ErrorCode.ERR_BindToBogus, "F2").WithArguments("A.F2(int)").WithLocation(7, 11), - // (10,11): error CS0570: 'A.F3(object, ref int)' is not supported by the language - // A.F3(x, ref y); - Diagnostic(ErrorCode.ERR_BindToBogus, "F3").WithArguments("A.F3(object, ref int)").WithLocation(10, 11)); + Diagnostic(ErrorCode.ERR_BindToBogus, "F2").WithArguments("A.F2(int)").WithLocation(7, 11)); - var method = comp.GetMember("A.F4"); - Assert.Equal("void A.F4(ref scoped R r)", method.ToDisplayString(SymbolDisplayFormat.TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeScoped))); + var method = comp.GetMember("A.F1"); + Assert.Equal("void A.F1(scoped R r)", method.ToDisplayString(SymbolDisplayFormat.TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeScoped))); var parameter = method.Parameters[0]; Assert.Equal(DeclarationScope.ValueScoped, parameter.Scope); + + method = comp.GetMember("A.F3"); + Assert.Equal("void A.F3(System.Object x, scoped ref System.Int32 y)", method.ToDisplayString(SymbolDisplayFormat.TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeScoped))); + parameter = method.Parameters[1]; + Assert.Equal(DeclarationScope.RefScoped, parameter.Scope); + + method = comp.GetMember("A.F4"); + Assert.Equal("void A.F4(scoped ref R r)", method.ToDisplayString(SymbolDisplayFormat.TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeScoped))); + parameter = method.Parameters[0]; + Assert.Equal(DeclarationScope.RefScoped, parameter.Scope); } [Fact] public void ExplicitAttribute_UnexpectedAttributeConstructor() { var source0 = -@".class private System.Runtime.CompilerServices.LifetimeAnnotationAttribute extends [mscorlib]System.Attribute +@".class private System.Runtime.CompilerServices.ScopedRefAttribute extends [mscorlib]System.Attribute { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig specialname rtspecialname instance void .ctor(bool isRefScoped, bool isValueScoped) cil managed { ret } } .class public sealed R extends [mscorlib]System.ValueType { @@ -244,13 +240,13 @@ .class public A .method public static void F1(valuetype R r) { .param [1] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor() = ( 01 00 00 00 ) // LifetimeAnnotationAttribute() + .custom instance void System.Runtime.CompilerServices.ScopedRefAttribute::.ctor(bool, bool) = ( 01 00 00 01 00 00 ) // ScopedRefAttribute(isRefScoped: false, isValueScoped: true) ret } .method public static void F2(object x, int32& y) { .param [2] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor() = ( 01 00 00 00 ) // LifetimeAnnotationAttribute() + .custom instance void System.Runtime.CompilerServices.ScopedRefAttribute::.ctor(bool, bool) = ( 01 00 01 00 00 00 ) // ScopedRefAttribute(isRefScoped: true, isValueScoped: false) ret } } @@ -269,7 +265,7 @@ static void Main() } }"; var comp = CreateCompilation(source1, references: new[] { ref0 }); - // https://github.com/dotnet/roslyn/issues/61647: If the [LifetimeAnnotation] scoped value is an int + // https://github.com/dotnet/roslyn/issues/61647: If the [ScopedRef] scoped value is an int // rather than a pair of bools, the compiler should reject attribute values that it does not recognize. comp.VerifyDiagnostics(); } @@ -289,19 +285,19 @@ public static void F(scoped R r) { } var comp = CreateCompilation(source); var expected = @"S..ctor(ref System.Int32 i) - [LifetimeAnnotation(True, False)] ref System.Int32 i + [ScopedRef] ref System.Int32 i void S.F(R r) - [LifetimeAnnotation(False, True)] R r + [ScopedRef] R r S S.op_Addition(S a, in R b) S a - [LifetimeAnnotation(True, False)] in R b + [ScopedRef] in R b System.Object S.this[in System.Int32 i].get - [LifetimeAnnotation(True, False)] in System.Int32 i + [ScopedRef] in System.Int32 i "; CompileAndVerify(comp, symbolValidator: module => { - Assert.Equal("System.Runtime.CompilerServices.LifetimeAnnotationAttribute", GetLifetimeAnnotationType(module).ToTestDisplayString()); - AssertLifetimeAnnotationAttributes(module, expected); + Assert.Equal("System.Runtime.CompilerServices.ScopedRefAttribute", GetScopedRefType(module).ToTestDisplayString()); + AssertScopedRefAttributes(module, expected); }); } @@ -321,8 +317,8 @@ public static void F(out int x, out R y) var comp = CreateCompilation(source); CompileAndVerify(comp, symbolValidator: module => { - Assert.Null(GetLifetimeAnnotationType(module)); - AssertLifetimeAnnotationAttributes(module, ""); + Assert.Null(GetScopedRefType(module)); + AssertScopedRefAttributes(module, ""); }); } @@ -342,8 +338,8 @@ public static void F(scoped out int x, scoped out R y) var comp = CreateCompilation(source); CompileAndVerify(comp, symbolValidator: module => { - Assert.Null(GetLifetimeAnnotationType(module)); - AssertLifetimeAnnotationAttributes(module, ""); + Assert.Null(GetScopedRefType(module)); + AssertScopedRefAttributes(module, ""); }); } @@ -357,15 +353,15 @@ public void EmitAttribute_DelegateParameters() var comp = CreateCompilation(source); var expected = @"void D.Invoke(in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x, R y) - [LifetimeAnnotation(True, False)] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x - [LifetimeAnnotation(False, True)] R y + [ScopedRef] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x + [ScopedRef] R y System.IAsyncResult D.BeginInvoke(in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x, R y, System.AsyncCallback callback, System.Object @object) - [LifetimeAnnotation(True, False)] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x - [LifetimeAnnotation(False, True)] R y + [ScopedRef] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x + [ScopedRef] R y System.AsyncCallback callback System.Object @object void D.EndInvoke(in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x, System.IAsyncResult result) - [LifetimeAnnotation(True, False)] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x + [ScopedRef] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 x System.IAsyncResult result "; CompileAndVerify( @@ -373,8 +369,8 @@ System.IAsyncResult result options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { - Assert.Equal("System.Runtime.CompilerServices.LifetimeAnnotationAttribute", GetLifetimeAnnotationType(module).ToTestDisplayString()); - AssertLifetimeAnnotationAttributes(module, expected); + Assert.Equal("System.Runtime.CompilerServices.ScopedRefAttribute", GetScopedRefType(module).ToTestDisplayString()); + AssertScopedRefAttributes(module, expected); }); } @@ -394,25 +390,24 @@ static void Main() var comp = CreateCompilation(source); var expected = @"void D.Invoke(in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i) - [LifetimeAnnotation(True, False)] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i + [ScopedRef] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i System.IAsyncResult D.BeginInvoke(in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i, System.AsyncCallback callback, System.Object @object) - [LifetimeAnnotation(True, False)] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i + [ScopedRef] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i System.AsyncCallback callback System.Object @object void D.EndInvoke(in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i, System.IAsyncResult result) - [LifetimeAnnotation(True, False)] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i + [ScopedRef] in modreq(System.Runtime.InteropServices.InAttribute) System.Int32 i System.IAsyncResult result void Program.<>c.
b__0_0(in System.Int32 i) - [LifetimeAnnotation(True, False)] in System.Int32 i - + [ScopedRef] in System.Int32 i "; CompileAndVerify( source, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { - Assert.Equal("System.Runtime.CompilerServices.LifetimeAnnotationAttribute", GetLifetimeAnnotationType(module).ToTestDisplayString()); - AssertLifetimeAnnotationAttributes(module, expected); + Assert.Equal("System.Runtime.CompilerServices.ScopedRefAttribute", GetScopedRefType(module).ToTestDisplayString()); + AssertScopedRefAttributes(module, expected); }); } @@ -431,15 +426,15 @@ void L(scoped in int i) { } var comp = CreateCompilation(source); var expected = @"void Program.g__L|0_0(in System.Int32 i) - [LifetimeAnnotation(True, False)] in System.Int32 i + [ScopedRef] in System.Int32 i "; CompileAndVerify( source, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { - Assert.Equal("System.Runtime.CompilerServices.LifetimeAnnotationAttribute", GetLifetimeAnnotationType(module).ToTestDisplayString()); - AssertLifetimeAnnotationAttributes(module, expected); + Assert.Equal("System.Runtime.CompilerServices.ScopedRefAttribute", GetScopedRefType(module).ToTestDisplayString()); + AssertScopedRefAttributes(module, expected); }); } @@ -461,13 +456,13 @@ static void Main() var comp = CreateCompilation(source); var expected = @"void <>f__AnonymousDelegate0.Invoke(in System.Int32 value) - [LifetimeAnnotation(True, False)] in System.Int32 value + [ScopedRef] in System.Int32 value R <>f__AnonymousDelegate1.Invoke(R value) - [LifetimeAnnotation(False, True)] R value + [ScopedRef] R value void Program.<>c.
b__0_0(in System.Int32 i) - [LifetimeAnnotation(True, False)] in System.Int32 i + [ScopedRef] in System.Int32 i R Program.<>c.
b__0_1(R r) - [LifetimeAnnotation(False, True)] R r + [ScopedRef] R r "; CompileAndVerify( source, @@ -475,20 +470,20 @@ static void Main() verify: Verification.Skipped, symbolValidator: module => { - Assert.Equal("System.Runtime.CompilerServices.LifetimeAnnotationAttribute", GetLifetimeAnnotationType(module).ToTestDisplayString()); - AssertLifetimeAnnotationAttributes(module, expected); + Assert.Equal("System.Runtime.CompilerServices.ScopedRefAttribute", GetScopedRefType(module).ToTestDisplayString()); + AssertScopedRefAttributes(module, expected); }); } - private static void AssertLifetimeAnnotationAttributes(ModuleSymbol module, string expected) + private static void AssertScopedRefAttributes(ModuleSymbol module, string expected) { - var actual = LifetimeAnnotationAttributesVisitor.GetString((PEModuleSymbol)module); + var actual = ScopedRefAttributesVisitor.GetString((PEModuleSymbol)module); AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, actual); } - private static NamedTypeSymbol GetLifetimeAnnotationType(ModuleSymbol module) + private static NamedTypeSymbol GetScopedRefType(ModuleSymbol module) { - return module.GlobalNamespace.GetMember("System.Runtime.CompilerServices.LifetimeAnnotationAttribute"); + return module.GlobalNamespace.GetMember("System.Runtime.CompilerServices.ScopedRefAttribute"); } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index 9d945efed5318..92854472e3261 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -6854,47 +6854,6 @@ static void F7(scoped in scoped s) { } VerifyParameterSymbol(comp.GetMember("Program.FA").Parameters[0], "out scoped s", RefKind.Out, DeclarationScope.RefScoped); } - [Fact] - public void ParameterScope_10() - { - var source0 = -@".class private System.Runtime.CompilerServices.LifetimeAnnotationAttribute extends [mscorlib]System.Attribute -{ - .method public hidebysig specialname rtspecialname instance void .ctor(bool isRefScoped, bool isValueScoped) cil managed { ret } -} -.class public sealed R extends [mscorlib]System.ValueType -{ - .custom instance void [mscorlib]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = (01 00 00 00) - .field public int32& modreq(int32) F -} -.class public A -{ - .method public static void F(valuetype R r) - { - .param [1] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor(bool, bool) = ( 01 00 00 00 00 00 ) // LifetimeAnnotationAttribute(isRefScoped: false, isValueScoped: false) - ret - } -} -"; - var ref0 = CompileIL(source0); - - var source1 = -@"class Program -{ - static void Main() - { - var r = new R(); - A.F(r); - } -}"; - var comp = CreateCompilation(source1, references: new[] { ref0 }); - comp.VerifyDiagnostics(); - - var method = comp.GetMember("A.F"); - VerifyParameterSymbol(method.Parameters[0], "R r", RefKind.None, DeclarationScope.Unscoped); - } - [WorkItem(62080, "https://github.com/dotnet/roslyn/issues/62080")] [Fact] public void ParameterScope_11() @@ -6930,23 +6889,16 @@ static void Main() public void ParameterScope_12() { var source0 = -@".class private System.Runtime.CompilerServices.LifetimeAnnotationAttribute extends [mscorlib]System.Attribute +@".class private System.Runtime.CompilerServices.ScopedRefAttribute extends [mscorlib]System.Attribute { - .method public hidebysig specialname rtspecialname instance void .ctor(bool isRefScoped, bool isValueScoped) cil managed { ret } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } .class public A { .method public static void F1([out] int32& i) { .param [1] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor(bool, bool) = ( 01 00 01 00 00 00 ) // LifetimeAnnotationAttribute(isRefScoped: true, isValueScoped: false) - ldnull - throw - } - .method public static void F2([out] int32& i) - { - .param [1] - .custom instance void System.Runtime.CompilerServices.LifetimeAnnotationAttribute::.ctor(bool, bool) = ( 01 00 00 00 00 00 ) // LifetimeAnnotationAttribute(isRefScoped: false, isValueScoped: false) + .custom instance void System.Runtime.CompilerServices.ScopedRefAttribute::.ctor() = ( 01 00 00 00 ) // ScopedRefAttribute() ldnull throw } @@ -6961,14 +6913,12 @@ static void Main() { int i; A.F1(out i); - A.F2(out i); } }"; var comp = CreateCompilation(source1, references: new[] { ref0 }); comp.VerifyDiagnostics(); VerifyParameterSymbol(comp.GetMember("A.F1").Parameters[0], "out System.Int32 i", RefKind.Out, DeclarationScope.RefScoped); - VerifyParameterSymbol(comp.GetMember("A.F2").Parameters[0], "out System.Int32 i", RefKind.Out, DeclarationScope.Unscoped); } [Fact] @@ -7303,7 +7253,7 @@ private static void VerifyParameterSymbol(ParameterSymbol parameter, string expe Assert.Equal(expectedScope, parameter.Scope); Assert.Equal(expectedDisplayString, parameter.ToDisplayString(displayFormatWithScoped)); - var attribute = parameter.GetAttributes().FirstOrDefault(a => a.GetTargetAttributeSignatureIndex(parameter, AttributeDescription.LifetimeAnnotationAttribute) != -1); + var attribute = parameter.GetAttributes().FirstOrDefault(a => a.GetTargetAttributeSignatureIndex(parameter, AttributeDescription.ScopedRefAttribute) != -1); Assert.Null(attribute); VerifyParameterSymbol(parameter.GetPublicSymbol(), expectedDisplayString, expectedRefKind, expectedScope); diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index e61298854268a..1959c70e93606 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -614,7 +614,7 @@ public void AllWellKnownTypes() case WellKnownType.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler: case WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute: case WellKnownType.System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute: - case WellKnownType.System_Runtime_CompilerServices_LifetimeAnnotationAttribute: + case WellKnownType.System_Runtime_CompilerServices_ScopedRefAttribute: case WellKnownType.System_MemoryExtensions: case WellKnownType.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute: // Not yet in the platform. @@ -976,7 +976,7 @@ public void AllWellKnownTypeMembers() case WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear: case WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor: case WellKnownMember.System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute__ctor: - case WellKnownMember.System_Runtime_CompilerServices_LifetimeAnnotationAttribute__ctor: + case WellKnownMember.System_Runtime_CompilerServices_ScopedRefAttribute__ctor: case WellKnownMember.System_MemoryExtensions__SequenceEqual_Span_T: case WellKnownMember.System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T: case WellKnownMember.System_MemoryExtensions__AsSpan_String: diff --git a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs index 6117c5f32428d..00c344d3ce050 100644 --- a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs +++ b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs @@ -1087,16 +1087,9 @@ internal bool HasNativeIntegerAttribute(EntityHandle token, out ImmutableArray tupleElementNames) diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index abe6c5d039722..951aeff1271b9 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -334,7 +334,7 @@ static AttributeDescription() private static readonly byte[][] s_signaturesOfNullableAttribute = { s_signature_HasThis_Void_Byte, s_signature_HasThis_Void_SzArray_Byte }; private static readonly byte[][] s_signaturesOfNullableContextAttribute = { s_signature_HasThis_Void_Byte }; private static readonly byte[][] s_signaturesOfNativeIntegerAttribute = { s_signature_HasThis_Void, s_signature_HasThis_Void_SzArray_Boolean }; - private static readonly byte[][] s_signaturesOfLifetimeAnnotationAttribute = { s_signature_HasThis_Void_Boolean_Boolean }; + private static readonly byte[][] s_signaturesOfScopedRefAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfInterpolatedStringArgumentAttribute = { s_signature_HasThis_Void_String, s_signature_HasThis_Void_SzArray_String }; // early decoded attributes: @@ -470,7 +470,7 @@ static AttributeDescription() internal static readonly AttributeDescription EnumeratorCancellationAttribute = new AttributeDescription("System.Runtime.CompilerServices", "EnumeratorCancellationAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription SkipLocalsInitAttribute = new AttributeDescription("System.Runtime.CompilerServices", "SkipLocalsInitAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription NativeIntegerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "NativeIntegerAttribute", s_signaturesOfNativeIntegerAttribute); - internal static readonly AttributeDescription LifetimeAnnotationAttribute = new AttributeDescription("System.Runtime.CompilerServices", "LifetimeAnnotationAttribute", s_signaturesOfLifetimeAnnotationAttribute); + internal static readonly AttributeDescription ScopedRefAttribute = new AttributeDescription("System.Runtime.CompilerServices", "ScopedRefAttribute", s_signaturesOfScopedRefAttribute); internal static readonly AttributeDescription ModuleInitializerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "ModuleInitializerAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription UnmanagedCallersOnlyAttribute = new AttributeDescription("System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription InterpolatedStringHandlerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "InterpolatedStringHandlerAttribute", s_signatures_HasThis_Void_Only); diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index e32700fdbd918..67710436f5cb8 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -522,7 +522,7 @@ internal enum WellKnownMember System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, System_Runtime_CompilerServices_RequiredMemberAttribute__ctor, System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute__ctor, - System_Runtime_CompilerServices_LifetimeAnnotationAttribute__ctor, + System_Runtime_CompilerServices_ScopedRefAttribute__ctor, System_MemoryExtensions__SequenceEqual_Span_T, System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T, diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 66117afc0bbae..ef9135e334a78 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3583,14 +3583,12 @@ static WellKnownMembers() 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type - // System_Runtime_CompilerServices_LifetimeAnnotationAttribute__ctor + // System_Runtime_CompilerServices_ScopedRefAttribute__ctor (byte)MemberFlags.Constructor, // Flags - (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_LifetimeAnnotationAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_ScopedRefAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId 0, // Arity - 2, // Method Signature + 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type - (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Boolean, - (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Boolean, // System_MemoryExtensions__SequenceEqual_Span_T (byte)(MemberFlags.Method | MemberFlags.Static), // Flags diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index 41bf3dc7e746d..4a51179a65f76 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -314,7 +314,7 @@ internal enum WellKnownType System_Text_StringBuilder, System_Runtime_CompilerServices_DefaultInterpolatedStringHandler, - System_Runtime_CompilerServices_LifetimeAnnotationAttribute, + System_Runtime_CompilerServices_ScopedRefAttribute, System_ArgumentNullException, @@ -633,7 +633,7 @@ internal static class WellKnownTypes "System.Text.StringBuilder", "System.Runtime.CompilerServices.DefaultInterpolatedStringHandler", - "System.Runtime.CompilerServices.LifetimeAnnotationAttribute", + "System.Runtime.CompilerServices.ScopedRefAttribute", "System.ArgumentNullException", "System.Runtime.CompilerServices.RequiredMemberAttribute", diff --git a/src/Compilers/Test/Utilities/CSharp/LifetimeAnnotationAttributesVisitor.cs b/src/Compilers/Test/Utilities/CSharp/LifetimeAnnotationAttributesVisitor.cs index 6b967d09b0193..d6dd72234b633 100644 --- a/src/Compilers/Test/Utilities/CSharp/LifetimeAnnotationAttributesVisitor.cs +++ b/src/Compilers/Test/Utilities/CSharp/LifetimeAnnotationAttributesVisitor.cs @@ -14,19 +14,19 @@ namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities { - internal sealed class LifetimeAnnotationAttributesVisitor : CSharpSymbolVisitor + internal sealed class ScopedRefAttributesVisitor : CSharpSymbolVisitor { internal static string GetString(PEModuleSymbol module) { var builder = new StringBuilder(); - var visitor = new LifetimeAnnotationAttributesVisitor(builder); + var visitor = new ScopedRefAttributesVisitor(builder); visitor.Visit(module); return builder.ToString(); } private readonly StringBuilder _builder; - private LifetimeAnnotationAttributesVisitor(StringBuilder builder) + private ScopedRefAttributesVisitor(StringBuilder builder) { _builder = builder; } @@ -73,7 +73,7 @@ public override void VisitProperty(PropertySymbol property) public override void VisitMethod(MethodSymbol method) { var parameters = method.Parameters; - if (!parameters.Any(p => TryGetLifetimeAnnotationAttribute((PEParameterSymbol)p, out _))) + if (!parameters.Any(p => TryGetScopedRefAttribute((PEParameterSymbol)p))) { return; } @@ -81,18 +81,18 @@ public override void VisitMethod(MethodSymbol method) foreach (var parameter in parameters) { _builder.Append(" "); - if (TryGetLifetimeAnnotationAttribute((PEParameterSymbol)parameter, out var pair)) + if (TryGetScopedRefAttribute((PEParameterSymbol)parameter)) { - _builder.Append($"[LifetimeAnnotation({pair.IsRefScoped}, {pair.IsValueScoped})] "); + _builder.Append($"[ScopedRef] "); } _builder.AppendLine(parameter.ToTestDisplayString()); } } - private bool TryGetLifetimeAnnotationAttribute(PEParameterSymbol parameter, out (bool IsRefScoped, bool IsValueScoped) pair) + private bool TryGetScopedRefAttribute(PEParameterSymbol parameter) { var module = ((PEModuleSymbol)parameter.ContainingModule).Module; - return module.HasLifetimeAnnotationAttribute(parameter.Handle, out pair); + return module.HasScopedRefAttribute(parameter.Handle); } } } diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index 200cfb8e6ecf0..4877aa66b5003 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -551,7 +551,7 @@ End Namespace WellKnownType.System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute, WellKnownType.System_MemoryExtensions, WellKnownType.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute, - WellKnownType.System_Runtime_CompilerServices_LifetimeAnnotationAttribute, + WellKnownType.System_Runtime_CompilerServices_ScopedRefAttribute, WellKnownType.System_MemoryExtensions ' Not available on all platforms. Continue For @@ -623,7 +623,7 @@ End Namespace WellKnownType.System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute, WellKnownType.System_MemoryExtensions, WellKnownType.System_Runtime_CompilerServices_CompilerFeatureRequiredAttribute, - WellKnownType.System_Runtime_CompilerServices_LifetimeAnnotationAttribute + WellKnownType.System_Runtime_CompilerServices_ScopedRefAttribute ' Not available on all platforms. Continue For Case WellKnownType.ExtSentinel @@ -715,7 +715,7 @@ End Namespace WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor, WellKnownMember.System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute__ctor, - WellKnownMember.System_Runtime_CompilerServices_LifetimeAnnotationAttribute__ctor, + WellKnownMember.System_Runtime_CompilerServices_ScopedRefAttribute__ctor, WellKnownMember.System_MemoryExtensions__SequenceEqual_Span_T, WellKnownMember.System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T, WellKnownMember.System_MemoryExtensions__AsSpan_String, @@ -867,7 +867,7 @@ End Namespace WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor, WellKnownMember.System_Diagnostics_CodeAnalysis_SetsRequiredMembersAttribute__ctor, - WellKnownMember.System_Runtime_CompilerServices_LifetimeAnnotationAttribute__ctor, + WellKnownMember.System_Runtime_CompilerServices_ScopedRefAttribute__ctor, WellKnownMember.System_MemoryExtensions__SequenceEqual_Span_T, WellKnownMember.System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T, WellKnownMember.System_MemoryExtensions__AsSpan_String, From df3a827f4a5c53caa3d4e0d2519bd3c96e156f5c Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 28 Jul 2022 10:14:24 -0700 Subject: [PATCH 2/3] Address feedback from Chuck --- .../Symbols/Metadata/PE/PEParameterSymbol.cs | 13 ++++----- ...beddedLifetimeAnnotationAttributeSymbol.cs | 3 -- .../AttributeTests_LifetimeAnnotation.cs | 28 +++++++++++++++++++ .../Attributes/AttributeDescription.cs | 3 +- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs index f80f17b66eb05..8ba3eff6c790e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs @@ -304,16 +304,13 @@ private PEParameterSymbol( Debug.Assert(refKind != RefKind.None); scope = DeclarationScope.RefScoped; } + else if (typeWithAnnotations.Type.IsRefLikeType) + { + scope = DeclarationScope.ValueScoped; + } else { - if (typeWithAnnotations.Type.IsRefLikeType) - { - scope = DeclarationScope.ValueScoped; - } - else - { - isBad = true; - } + isBad = true; } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs index fed825aa6af63..faff4d894041f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs @@ -3,10 +3,7 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.CSharp.Symbols { diff --git a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs index d017899380245..4817f4c893fb4 100644 --- a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs +++ b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs @@ -72,6 +72,29 @@ [ScopedRef] ref System.Int32 i }); } + [Fact] + public void ExplicitAttribute_MissingConstructor() + { + var source1 = +@"namespace System.Runtime.CompilerServices +{ + public sealed class ScopedRefAttribute : Attribute + { + public ScopedRefAttribute(int i) { } + } +}"; + var source2 = +@"class Program +{ + public static void F(scoped ref int i) { } +}"; + var comp = CreateCompilation(new[] { source1, source2 }); + comp.VerifyEmitDiagnostics( + // (3,26): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.ScopedRefAttribute..ctor' + // public static void F(scoped ref int i) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "scoped ref int i").WithArguments("System.Runtime.CompilerServices.ScopedRefAttribute", ".ctor").WithLocation(3, 26)); + } + [WorkItem(62124, "https://github.com/dotnet/roslyn/issues/62124")] [Fact] public void ExplicitAttribute_ReferencedInSource_01() @@ -211,6 +234,11 @@ static void Main() var parameter = method.Parameters[0]; Assert.Equal(DeclarationScope.ValueScoped, parameter.Scope); + method = comp.GetMember("A.F2"); + Assert.Equal("void A.F2(System.Int32 y)", method.ToDisplayString(SymbolDisplayFormat.TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeScoped))); + parameter = method.Parameters[0]; + Assert.Equal(DeclarationScope.Unscoped, parameter.Scope); + method = comp.GetMember("A.F3"); Assert.Equal("void A.F3(System.Object x, scoped ref System.Int32 y)", method.ToDisplayString(SymbolDisplayFormat.TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeScoped))); parameter = method.Parameters[1]; diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index 951aeff1271b9..205367fae0207 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -334,7 +334,6 @@ static AttributeDescription() private static readonly byte[][] s_signaturesOfNullableAttribute = { s_signature_HasThis_Void_Byte, s_signature_HasThis_Void_SzArray_Byte }; private static readonly byte[][] s_signaturesOfNullableContextAttribute = { s_signature_HasThis_Void_Byte }; private static readonly byte[][] s_signaturesOfNativeIntegerAttribute = { s_signature_HasThis_Void, s_signature_HasThis_Void_SzArray_Boolean }; - private static readonly byte[][] s_signaturesOfScopedRefAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfInterpolatedStringArgumentAttribute = { s_signature_HasThis_Void_String, s_signature_HasThis_Void_SzArray_String }; // early decoded attributes: @@ -470,7 +469,7 @@ static AttributeDescription() internal static readonly AttributeDescription EnumeratorCancellationAttribute = new AttributeDescription("System.Runtime.CompilerServices", "EnumeratorCancellationAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription SkipLocalsInitAttribute = new AttributeDescription("System.Runtime.CompilerServices", "SkipLocalsInitAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription NativeIntegerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "NativeIntegerAttribute", s_signaturesOfNativeIntegerAttribute); - internal static readonly AttributeDescription ScopedRefAttribute = new AttributeDescription("System.Runtime.CompilerServices", "ScopedRefAttribute", s_signaturesOfScopedRefAttribute); + internal static readonly AttributeDescription ScopedRefAttribute = new AttributeDescription("System.Runtime.CompilerServices", "ScopedRefAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription ModuleInitializerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "ModuleInitializerAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription UnmanagedCallersOnlyAttribute = new AttributeDescription("System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription InterpolatedStringHandlerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "InterpolatedStringHandlerAttribute", s_signatures_HasThis_Void_Only); From 98dbd1509aa4fd5a40a700a3fa0d273ef6afd348 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 28 Jul 2022 14:20:26 -0700 Subject: [PATCH 3/3] tweaks --- ...beddedLifetimeAnnotationAttributeSymbol.cs | 2 +- .../AttributeTests_LifetimeAnnotation.cs | 38 ++++++------------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs index faff4d894041f..7cabcd56d7b5a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedLifetimeAnnotationAttributeSymbol.cs @@ -22,7 +22,7 @@ public SynthesizedEmbeddedScopedRefAttributeSymbol( new SynthesizedEmbeddedAttributeConstructorWithBodySymbol( this, getParameters: m => ImmutableArray.Empty, - getConstructorBody: (f, s, p) => { })); + getConstructorBody: (_, _, _) => { })); } public override ImmutableArray Constructors => _constructors; diff --git a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs index 4817f4c893fb4..8363034cc9644 100644 --- a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs +++ b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs @@ -130,40 +130,24 @@ [ScopedRef] class Program [ScopedRef] static object M1() => throw null; [ScopedRef] static object M2() => throw null; static void M3<[ScopedRef] T>() { } -}"; - var comp = CreateCompilation(new[] { ScopedRefAttributeDefinition, source }); +} +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)] + public sealed class ScopedRefAttribute : Attribute + { + } +} +"; + var comp = CreateCompilation(source); // https://github.com/dotnet/roslyn/issues/62124: Re-enable check for ScopedRefAttribute in ReportExplicitUseOfReservedAttributes. comp.VerifyDiagnostics( - // (3,10): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // [module: ScopedRef] - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(3, 10), - // (4,2): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // [ScopedRef] class Program - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(4, 2), - // (6,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // [ScopedRef] object F; - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(6, 6), // (6,24): warning CS0169: The field 'Program.F' is never used // [ScopedRef] object F; Diagnostic(ErrorCode.WRN_UnreferencedField, "F").WithArguments("Program.F").WithLocation(6, 24), - // (7,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // [ScopedRef] event EventHandler E; - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(7, 6), // (7,36): warning CS0067: The event 'Program.E' is never used // [ScopedRef] event EventHandler E; - Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("Program.E").WithLocation(7, 36), - // (8,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // [ScopedRef] object P { get; } - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(8, 6), - // (9,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // [ScopedRef] static object M1() => throw null; - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(9, 6), - // (10,6): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // [ScopedRef] static object M2() => throw null; - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(10, 6), - // (11,21): error CS0592: Attribute 'ScopedRef' is not valid on this declaration type. It is only valid on 'parameter' declarations. - // static void M3<[ScopedRef] T>() { } - Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "ScopedRef").WithArguments("ScopedRef", "parameter").WithLocation(11, 21)); + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("Program.E").WithLocation(7, 36)); } [Fact]