Conversation
2751f37 to
1574564
Compare
3f8b7b2 to
6442a41
Compare
85d875c to
e1c0157
Compare
e1c0157 to
7884b57
Compare
src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests_LifetimeAnnotation.cs
Show resolved
Hide resolved
| A possible workaround is to change the method signature to pass the parameter by `ref` instead. | ||
| Possible workarounds are: | ||
| 1. Use `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute` to mark the reference as unscoped. | ||
| ```csharp |
There was a problem hiding this comment.
nit: other csharp blocks are left-indented. Not sure whether it's material (does that affect markup rendering on GitHub or docs.microsoft.com), but I'd stick with that to be safe. #Closed
There was a problem hiding this comment.
Without indenting, subsequent bullets start at 1.
| if (_moduleSymbol.Module.HasLifetimeAnnotationAttribute(_handle, out var pair)) | ||
| if (_moduleSymbol.Module.HasUnscopedRefAttribute(_handle)) | ||
| { | ||
| scope = DeclarationScope.Unscoped; |
There was a problem hiding this comment.
Should we mark the parameter as bad if there's both attributes? #Closed
| } | ||
|
|
||
| internal sealed override DeclarationScope Scope => _packedFlags.Scope; | ||
| internal sealed override DeclarationScope DeclaredScope => _packedFlags.Scope; |
There was a problem hiding this comment.
nit: Is PEParameterSymbol.DeclaredScope reachable (aside from the use on next line)? #Resolved
There was a problem hiding this comment.
It looks like PEParameterSymbol.DeclaredScope is only used below, so perhaps we could limit DeclaredScope to source symbols only. That change may be a little involved though, so perhaps that could be done later if necessary.
| if (ParameterHelpers.RequiresLifetimeAnnotationAttribute(this)) | ||
| { | ||
| AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, Scope)); | ||
| AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, DeclaredScope)); |
There was a problem hiding this comment.
I agree, there shouldn't be a difference here, but I think I prefer DeclaredScope since that is what was declared.
There was a problem hiding this comment.
Still nit but want to clarify my reasoning: Declared scope is only a step towards producing the real/effective scope. I think most places should use the real/effective scope unless there's a special reason. When it comes to emitting (like here), clearly we should use the real/effective scope, not its precedessor. If we added any more factors into the computations of real/effective scope, we'd want them to affect what we emit.
There was a problem hiding this comment.
Currently, we're emitting implicitly scoped parameters with no [ScopedRef] attribute. If we use EffectiveScope for emit, then emitting [UnscopedRef] out int i (where the EffectiveScope is Unscoped) will require ensuring an [UnscopedRef] attribute is emitted, perhaps by assuming an [UnscopedRef] attribute was specified in source. Instead, if we use DeclaredScope here (which is perhaps poorly named since DeclaredScope is (implicitly )RefScoped for out int i), then any [UnscopedRef] from source will provided the expected result in metadata.
A better alternative might be to emit implicitly scoped parameters with a [ScopedRef] attribute. Then EffectiveScope may be simpler here. #63078
| if (ParameterHelpers.RequiresLifetimeAnnotationAttribute(this)) | ||
| { | ||
| AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, Scope)); | ||
| AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeLifetimeAnnotationAttribute(this, DeclaredScope)); |
| } | ||
| return scope; | ||
|
|
||
| static bool hasUnscopedRefAttribute(MethodSymbol? containingMethod, NamedTypeSymbol? containingType) |
| }"; | ||
| var comp = CreateCompilation(new[] { source, UnscopedRefAttributeDefinition }); | ||
| comp.VerifyEmitDiagnostics( | ||
| // (6,23): error CS9064: UnscopedRefAttribute can only be applied to parameters that are passed by reference and implicitly scoped. |
There was a problem hiding this comment.
UnscopedRefAttribute can also be applied to ref parameters of ref struct types.
There was a problem hiding this comment.
Updated the text to cover the two cases as we discussed.
| t3 = default; | ||
| return ref t3; | ||
| } | ||
| public ref T F4A([UnscopedRef] scoped out T t4) |
There was a problem hiding this comment.
I'd expect an error (this is not "implicitly-scoped") #Closed
jcouv
left a comment
There was a problem hiding this comment.
Done with review pass (iteration 8)
| } | ||
| public class A<T> | ||
| { | ||
| public ref T F1A(ref R<T> r1) |
There was a problem hiding this comment.
Looking at the verification below (VerifyParameterSymbol(baseType.GetMethod("F1A").Parameters[0], "ref R<System.Int32> r1", RefKind.Ref, DeclarationScope.Unscoped);), it seems we're not treating this parameter as scoped. But shouldn't it be implicitly-scoped according to the rule "ref parameters which refer to a ref struct"? #Closed
There was a problem hiding this comment.
The change to treat ref parameters to ref struct types as implicitly scoped is handled in a subsequent PR: #62778.
|
|
||
| internal abstract bool MustCallMethodsDirectly { get; } | ||
|
|
||
| internal abstract bool HasUnscopedRefAttribute { get; } |
333fred
left a comment
There was a problem hiding this comment.
Done review pass (commit 11). I did not look at tests yet.
...p/Portable/Symbols/Attributes/WellKnownAttributeData/ParameterEarlyWellKnownAttributeData.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs
Show resolved
Hide resolved
71f521a to
df68917
Compare
| public void UnscopedRefAttribute_Method_01(string type) | ||
| { | ||
| var source = | ||
| $@"using System.Diagnostics.CodeAnalysis; |
There was a problem hiding this comment.
Nit: raw interpolated strings would be more readable here :).
See dotnet/runtime#72074.
See low-level-struct-improvements.md.
Corresponding spec update: dotnet/csharplang#6329
Fixes #62780.
Relates to test plan #59194