Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename LifetimeAnnotationAttribute to ScopedRefAttribute and simplify #63009

Merged
merged 3 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
29 changes: 14 additions & 15 deletions src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// The behavior of the C# command-line compiler is as follows:
Expand Down Expand Up @@ -99,7 +99,7 @@ internal sealed override ImmutableArray<NamedTypeSymbol> GetEmbeddedTypes(Bindin
builder.AddIfNotNull(_lazyNullableContextAttribute);
builder.AddIfNotNull(_lazyNullablePublicOnlyAttribute);
builder.AddIfNotNull(_lazyNativeIntegerAttribute);
builder.AddIfNotNull(_lazyLifetimeAnnotationAttribute);
builder.AddIfNotNull(_lazyScopedRefAttribute);

return builder.ToImmutableAndFree();
}
Expand Down Expand Up @@ -251,17 +251,17 @@ internal override SynthesizedAttributeData SynthesizeNativeIntegerAttribute(Well
return base.SynthesizeNativeIntegerAttribute(member, arguments);
}

internal override SynthesizedAttributeData SynthesizeLifetimeAnnotationAttribute(WellKnownMember member, ImmutableArray<TypedConstant> 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<TypedConstant>.Empty,
ImmutableArray<KeyValuePair<string, TypedConstant>>.Empty);
}

return base.SynthesizeLifetimeAnnotationAttribute(member, arguments);
return base.SynthesizeScopedRefAttribute(member);
}

protected override SynthesizedAttributeData TrySynthesizeIsReadOnlyAttribute()
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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<T>(
ref T symbol,
Expand Down
18 changes: 6 additions & 12 deletions src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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<TypedConstant> 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()
Expand Down Expand Up @@ -1811,9 +1805,9 @@ internal void EnsureNativeIntegerAttributeExists()
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute);
}

internal void EnsureLifetimeAnnotationAttributeExists()
internal void EnsureScopedRefAttributeExists()
{
EnsureEmbeddableAttributeExists(EmbeddableAttributes.LifetimeAnnotationAttribute);
EnsureEmbeddableAttributeExists(EmbeddableAttributes.ScopedRefAttribute);
}

#nullable enable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,7 @@ internal override ITypeSymbolInternal CommonGetWellKnownType(WellKnownType wellk
ImmutableArray<KeyValuePair<WellKnownMember, TypedConstant>> namedArguments = default,
bool isOptionalUse = false)
{
UseSiteInfo<AssemblySymbol> 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)
{
Expand All @@ -413,7 +412,7 @@ internal override ITypeSymbolInternal CommonGetWellKnownType(WellKnownType wellk
var builder = new ArrayBuilder<KeyValuePair<string, TypedConstant>>(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 ...
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ internal enum EmbeddableAttributes
NullableContextAttribute = 0x10,
NullablePublicOnlyAttribute = 0x20,
NativeIntegerAttribute = 0x40,
LifetimeAnnotationAttribute = 0x80,
ScopedRefAttribute = 0x80,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ private PEParameterSymbol(
if (inOutFlags == ParameterAttributes.Out)
{
refKind = RefKind.Out;
scope = DeclarationScope.RefScoped;
}
else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle))
{
Expand All @@ -294,16 +293,24 @@ 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 if (typeWithAnnotations.Type.IsRefLikeType)
{
scope = DeclarationScope.ValueScoped;
}
else
{
scope = scopeOpt.GetValueOrDefault();
isBad = true;
}
}
}
Expand Down Expand Up @@ -980,16 +987,6 @@ public override ImmutableArray<SyntaxReference> 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<CSharpAttributeData> GetAttributes()
{
if (_lazyCustomAttributes.IsDefault)
Expand Down Expand Up @@ -1031,7 +1028,7 @@ public override ImmutableArray<CSharpAttributeData> GetAttributes()
out _,
filterIsReadOnlyAttribute ? AttributeDescription.IsReadOnlyAttribute : default,
out _,
AttributeDescription.LifetimeAnnotationAttribute,
AttributeDescription.ScopedRefAttribute,
out _,
default);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -322,12 +322,12 @@ internal static bool RequiresLifetimeAnnotationAttribute(ParameterSymbol paramet
return true;
}

internal static void EnsureLifetimeAnnotationAttributeExists(PEModuleBuilder moduleBuilder, ImmutableArray<ParameterSymbol> parameters)
internal static void EnsureScopedRefAttributeExists(PEModuleBuilder moduleBuilder, ImmutableArray<ParameterSymbol> 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<ParameterSymbol> parameters, BindingDiagnosticBag diagnostics, bool modifyCompilation)
internal static void EnsureScopedRefAttributeExists(CSharpCompilation? compilation, ImmutableArray<ParameterSymbol> 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.
Expand All @@ -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<ParameterSymbol> parameters, BindingDiagnosticBag? diagnostics, bool modifyCompilation, PEModuleBuilder? moduleBuilder)
private static void EnsureScopedRefAttributeExists(CSharpCompilation compilation, ImmutableArray<ParameterSymbol> 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);
}
}
}
Expand Down
Loading