-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
This issue is referenced in source/test.
Background and Motivation
Represent ref modifier for fields and the related scoped modifier for parameters and locals (see language proposal).
ref fields:
readonly ref struct Ref<T>
{
private readonly ref T _t;
public Ref(ref T t) { _t = ref t; }
}
readonly ref struct ReadOnlyRef<T>
{
private readonly ref readonly T _t;
public ReadOnlyRef(ref T t) { _t = ref t; }
}scoped parameters and locals:
static void F(scoped ref int x, ref int y)
{
scoped Ref<int> r = new Ref<int>(ref x);
}Proposed API
Symbols
namespace Microsoft.CodeAnalysis
{
public interface IFieldSymbol : ISymbol
{
+ /// <summary>
+ /// Returns the RefKind of the field.
+ /// </summary>
+ RefKind RefKind { get; }
+ /// <summary>
+ /// Custom modifiers associated with the ref modifier, or an empty array if there are none.
+ /// </summary>
+ ImmutableArray<CustomModifier> RefCustomModifiers { get; }
}
public interface ILocalSymbol : ISymbol
{
+ /// <summary>
+ /// Returns true if the local ref or value is scoped to the current method.
+ /// </summary>
+ bool IsScoped { get; }
}
public interface IParameterSymbol : ISymbol
{
+ /// <summary>
+ /// Returns true if the parameter ref or value is scoped to the current method.
+ /// </summary>
+ bool IsScoped { get; }
}
}Syntax
SyntaxKind.ScopedKeyword is added.
ScopedTypeSyntax is added that combines a scoped keyword and following type syntax.
If the type following scoped includes a ref, ref readonly, in, or out, the type is represented as a nested RefTypeSyntax.
namespace Microsoft.CodeAnalysis.CSharp
{
public enum SyntaxKind
{
+ /// <summary>Represents <see langword="scoped"/>.</summary>
+ ScopedKeyword = 8447,
}
public class SyntaxFactory
{
+ public static ScopedTypeSyntax ScopedType(SyntaxToken scopedKeyword, TypeSyntax type);
}
}
namespace Microsoft.CodeAnalysis.CSharp.Syntax
{
+ public sealed class ScopedTypeSyntax : TypeSyntax
+ {
+ public SyntaxToken ScopedKeyword { get; }
+ public TypeSyntax Type { get; }
+
+ public ScopedTypeSyntax Update(SyntaxToken scopedKeyword, TypeSyntax type);
+
+ public ScopedTypeSyntax WithScopedKeyword(SyntaxToken scopedKeyword);
+ public ScopedTypeSyntax WithType(TypeSyntax type);
+ }
}Metadata encoding
ScopedRefAttribute is used by the compiler to emit scoped modifiers to metadata.
The attribute type definition is synthesized by the compiler if missing from the compilation.
namespace System.Runtime.CompilerServices
{
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ internal sealed class ScopedRefAttribute : Attribute
+ {
+ }
}Usage Examples
Using RefTypeSyntax is a change for ParameterSyntax which currently represents ref keywords in ParameterSyntax.Modifiers. The proposal is to use RefTypeSyntax for ref keywords in parameters within scoped types only, to avoid a breaking change for C#10 syntax.
For example, the parameters from static void M(ref int x, scoped ref int y) will be represented as:
SyntaxFactory.ParameterList(
SyntaxFactory.Parameter(
modifiers: SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.RefKeyword)),
type: SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)),
identifier: "x"),
SyntaxFactory.Parameter(
modifiers: default,
type: SyntaxFactory.ScopedType(
SyntaxFactory.Token(SyntaxKind.ScopedKeyword),
SyntaxFactory.RefType(
SyntaxFactory.Token(SyntaxKind.RefKeyword),
SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)))),
identifier: "y"));