Skip to content

Commit

Permalink
Add public API for ref like type parameters (#73335)
Browse files Browse the repository at this point in the history
Related to #73330.
  • Loading branch information
AlekseyTs committed May 7, 2024
1 parent 449738c commit 319fc7c
Show file tree
Hide file tree
Showing 40 changed files with 176 additions and 108 deletions.
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8673,7 +8673,7 @@ private void CheckReceiverAndRuntimeSupportForSymbolAccess(SyntaxNode node, Boun
}
}

if (receiverOpt is { Type: TypeParameterSymbol { AllowByRefLike: true } } &&
if (receiverOpt is { Type: TypeParameterSymbol { AllowsByRefLike: true } } &&
isNotImplementableInstanceMember(symbol))
{
Error(diagnostics, ErrorCode.ERR_BadNonVirtualInterfaceMemberAccessOnAllowsRefLike, node);
Expand Down
8 changes: 4 additions & 4 deletions src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3570,28 +3570,28 @@ private BoundExpression BindIsOperator(BinaryExpressionSyntax node, BindingDiagn
// a restricted type cannot be boxed or unboxed into.
if (targetType.IsRestrictedType() || operandType.IsRestrictedType())
{
if (targetType is TypeParameterSymbol { AllowByRefLike: true })
if (targetType is TypeParameterSymbol { AllowsByRefLike: true })
{
if (!operandType.IsRefLikeType && operandType is not TypeParameterSymbol)
{
return null;
}
}
else if (operandType is not TypeParameterSymbol { AllowByRefLike: true })
else if (operandType is not TypeParameterSymbol { AllowsByRefLike: true })
{
if (targetType.IsRefLikeType)
{
if (operandType is TypeParameterSymbol)
{
Debug.Assert(operandType is TypeParameterSymbol { AllowByRefLike: false });
Debug.Assert(operandType is TypeParameterSymbol { AllowsByRefLike: false });
return ConstantValue.False;
}
}
else if (operandType.IsRefLikeType)
{
if (targetType is TypeParameterSymbol)
{
Debug.Assert(targetType is TypeParameterSymbol { AllowByRefLike: false });
Debug.Assert(targetType is TypeParameterSymbol { AllowsByRefLike: false });
return ConstantValue.False;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,7 @@ private void GetDisposalInfoForEnumerator(SyntaxNode syntax, ref ForEachEnumerat
{
Debug.Assert(!enumeratorType.IsRefLikeType); // Ref like types are supposed to be structs, therefore, sealed.

if (enumeratorType is TypeParameterSymbol { AllowByRefLike: true })
if (enumeratorType is TypeParameterSymbol { AllowsByRefLike: true })
{
Error(diagnostics, ErrorCode.ERR_BadAllowByRefLikeEnumerator, expr.Syntax, enumeratorType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2829,8 +2829,8 @@ public bool HasImplicitTypeParameterConversion(TypeParameterSymbol source, TypeS
return true;
}

if (destination is TypeParameterSymbol { AllowByRefLike: false } &&
!source.AllowByRefLike &&
if (destination is TypeParameterSymbol { AllowsByRefLike: false } &&
!source.AllowsByRefLike &&
source.DependsOn((TypeParameterSymbol)destination))
{
return true;
Expand All @@ -2849,7 +2849,7 @@ private bool HasImplicitReferenceTypeParameterConversion(TypeParameterSymbol sou
return false; // Not a reference conversion.
}

if (source.AllowByRefLike)
if (source.AllowsByRefLike)
{
return false;
}
Expand All @@ -2872,7 +2872,7 @@ private bool HasImplicitReferenceTypeParameterConversion(TypeParameterSymbol sou
}

// * From T to a type parameter U, provided T depends on U.
if (destination is TypeParameterSymbol { AllowByRefLike: false } &&
if (destination is TypeParameterSymbol { AllowsByRefLike: false } &&
source.DependsOn((TypeParameterSymbol)destination))
{
return true;
Expand Down Expand Up @@ -2979,7 +2979,7 @@ private bool IsRefLikeOrAllowsByRefLikeImplementingVarianceCompatibleInterface(T
{
if (typeToCheck is TypeParameterSymbol typeParameter)
{
return typeParameter.AllowByRefLike && HasVarianceCompatibleInterfaceInEffectiveInterfaceSet(typeParameter, targetInterfaceType, ref useSiteInfo);
return typeParameter.AllowsByRefLike && HasVarianceCompatibleInterfaceInEffectiveInterfaceSet(typeParameter, targetInterfaceType, ref useSiteInfo);
}
else if (typeToCheck.IsRefLikeType)
{
Expand Down Expand Up @@ -3202,7 +3202,7 @@ private bool HasImplicitBoxingTypeParameterConversion(TypeParameterSymbol source
return false; // Not a boxing conversion; both source and destination are references.
}

if (source.AllowByRefLike)
if (source.AllowsByRefLike)
{
return false;
}
Expand All @@ -3225,7 +3225,7 @@ private bool HasImplicitBoxingTypeParameterConversion(TypeParameterSymbol source
}

// SPEC: From T to a type parameter U, provided T depends on U
if (destination is TypeParameterSymbol { AllowByRefLike: false } d &&
if (destination is TypeParameterSymbol { AllowsByRefLike: false } d &&
source.DependsOn(d))
{
return true;
Expand Down Expand Up @@ -3480,7 +3480,7 @@ private bool HasExplicitReferenceTypeParameterConversion(TypeSymbol source, Type
TypeParameterSymbol s = source as TypeParameterSymbol;
TypeParameterSymbol t = destination as TypeParameterSymbol;

if (s?.AllowByRefLike == true || t?.AllowByRefLike == true)
if (s?.AllowsByRefLike == true || t?.AllowsByRefLike == true)
{
return false;
}
Expand Down Expand Up @@ -3532,7 +3532,7 @@ private bool HasUnboxingTypeParameterConversion(TypeSymbol source, TypeSymbol de
TypeParameterSymbol s = source as TypeParameterSymbol;
TypeParameterSymbol t = destination as TypeParameterSymbol;

if (s?.AllowByRefLike == true || t?.AllowByRefLike == true)
if (s?.AllowsByRefLike == true || t?.AllowsByRefLike == true)
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,8 +718,8 @@ private void GetAllBuiltInOperators(BinaryOperatorKind kind, bool isChecked, Bou
GetReferenceEquality(kind, operators);
Debug.Assert(operators.Count == 1);

if ((left.Type is TypeParameterSymbol { AllowByRefLike: true } && right.IsLiteralNull()) ||
(right.Type is TypeParameterSymbol { AllowByRefLike: true } && left.IsLiteralNull()))
if ((left.Type is TypeParameterSymbol { AllowsByRefLike: true } && right.IsLiteralNull()) ||
(right.Type is TypeParameterSymbol { AllowsByRefLike: true } && left.IsLiteralNull()))
{
BinaryOperatorSignature op = operators[0];
Debug.Assert(op.LeftType.IsObjectType());
Expand Down Expand Up @@ -776,7 +776,7 @@ static bool isUtf8ByteRepresentation(BoundExpression value)

Conversion getOperandConversionForAllowByRefLikeNullCheck(bool isChecked, BoundExpression operand, TypeSymbol objectType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
{
return (operand.Type is TypeParameterSymbol { AllowByRefLike: true }) ? Conversion.Boxing : Conversions.ClassifyConversionFromExpression(operand, objectType, isChecked: isChecked, ref useSiteInfo);
return (operand.Type is TypeParameterSymbol { AllowsByRefLike: true }) ? Conversion.Boxing : Conversions.ClassifyConversionFromExpression(operand, objectType, isChecked: isChecked, ref useSiteInfo);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ private void EmitBinaryCondOperator(BoundBinaryOperator binOp, bool sense)
{
if (!constant.IsFloating)
{
if (comparand is BoundConversion { Type.SpecialType: SpecialType.System_Object, ConversionKind: ConversionKind.Boxing, Operand.Type: TypeParameterSymbol { AllowByRefLike: true } } &&
if (comparand is BoundConversion { Type.SpecialType: SpecialType.System_Object, ConversionKind: ConversionKind.Boxing, Operand.Type: TypeParameterSymbol { AllowsByRefLike: true } } &&
constant.IsNull)
{
// Boxing is not supported for ref like type parameters, therefore the code that we usually emit 'box; ldnull; ceq/cgt'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ private static bool AreTypeParametersEqual(TypeParameterSymbol type, TypeParamet
// edit. Furthermore, comparing constraint types might lead to a cycle.
Debug.Assert(type.HasConstructorConstraint == other.HasConstructorConstraint);
Debug.Assert(type.HasValueTypeConstraint == other.HasValueTypeConstraint);
Debug.Assert(type.AllowByRefLike == other.AllowByRefLike);
Debug.Assert(type.AllowsByRefLike == other.AllowsByRefLike);
Debug.Assert(type.HasUnmanagedTypeConstraint == other.HasUnmanagedTypeConstraint);
Debug.Assert(type.HasReferenceTypeConstraint == other.HasReferenceTypeConstraint);
Debug.Assert(type.ConstraintTypesNoUseSiteDiagnostics.Length == other.ConstraintTypesNoUseSiteDiagnostics.Length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ bool Cci.IGenericParameter.AllowByRefLike
{
get
{
return AdaptedTypeParameterSymbol.AllowByRefLike;
return AdaptedTypeParameterSymbol.AllowsByRefLike;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected override bool AllowByRefLike
{
get
{
return UnderlyingTypeParameter.AdaptedTypeParameterSymbol.AllowByRefLike;
return UnderlyingTypeParameter.AdaptedTypeParameterSymbol.AllowsByRefLike;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ private static bool IsSameOrNestedType(NamedTypeSymbol type, NamedTypeSymbol oth
=> WellKnownMember.Microsoft_CodeAnalysis_Runtime_LocalStoreTracker__LogLocalStoreUnmanaged,
_ when variableType.IsRefLikeType && !hasOverriddenToString(variableType)
=> null, // not possible to invoke ToString on ref struct that doesn't override it
_ when variableType is TypeParameterSymbol { AllowByRefLike: true }
_ when variableType is TypeParameterSymbol { AllowsByRefLike: true }
=> null, // not possible to invoke ToString on ref struct type parameter
_ when variableType.TypeKind is TypeKind.Struct
// we'll emit ToString constrained virtcall to avoid boxing the struct
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,7 @@ public BoundExpression Convert(TypeSymbol type, BoundExpression arg, bool allowB
Conversion c = Compilation.Conversions.ClassifyConversionFromExpression(arg, type, isChecked: false, ref useSiteInfo);

if (allowBoxingByRefLikeTypeParametersToObject && !c.Exists &&
arg.Type is TypeParameterSymbol { AllowByRefLike: true } && type.IsObjectType())
arg.Type is TypeParameterSymbol { AllowsByRefLike: true } && type.IsObjectType())
{
c = Conversion.Boxing;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ public override void VisitParameter(IParameterSymbol symbol)

if (symbol.ScopedKind == ScopedKind.ScopedValue &&
symbol.RefKind == RefKind.None &&
!(symbol.IsParams && symbol.Type.IsRefLikeType))
!(symbol.IsParams && symbol.Type is { IsRefLikeType: true } or ITypeParameterSymbol { AllowsByRefLike: true }))
{
AddKeyword(SyntaxKind.ScopedKeyword);
AddSpace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public override bool HasValueTypeConstraint
get { return false; }
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get
{
Expand Down
5 changes: 3 additions & 2 deletions src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ public bool SupportsRuntimeCapability(RuntimeCapability capability)
return this.RuntimeSupportsStaticAbstractMembersInInterfaces;
case RuntimeCapability.InlineArrayTypes:
return this.RuntimeSupportsInlineArrayTypes;
case RuntimeCapability.ByRefLikeGenerics:
return this.RuntimeSupportsByRefLikeGenerics;
}

return false;
Expand Down Expand Up @@ -480,9 +482,8 @@ internal bool RuntimeSupportsInlineArrayTypes
/// <summary>
/// Figure out if the target runtime supports inline array types.
/// </summary>
internal bool RuntimeSupportsByRefLikeGenerics // PROTOTYPE(RefStructInterfaces): Implement public API.
internal bool RuntimeSupportsByRefLikeGenerics
{
// PROTOTYPE(RefStructInterfaces): Implement VB side.
// Keep in sync with VB's AssemblySymbol.RuntimeSupportsByRefLikeGenerics
get
{
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ internal static class ConstraintsHelper

diagnosticsBuilder.Free();

if (typeParameter.AllowByRefLike)
if (typeParameter.AllowsByRefLike)
{
if (inherited)
{
Expand Down Expand Up @@ -936,7 +936,7 @@ private static bool HasDuplicateInterfaces(NamedTypeSymbol type, ConsList<TypeSy

if (typeArgument.Type.IsRefLikeTypeOrAllowsByRefLike())
{
if (typeParameter.AllowByRefLike)
if (typeParameter.AllowsByRefLike)
{
if (args.CurrentCompilation.SourceModule != typeParameter.ContainingModule)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public override bool HasValueTypeConstraint
}
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ public static bool HaveSameConstraints(TypeParameterSymbol typeParameter1, TypeM
if ((typeParameter1.HasConstructorConstraint != typeParameter2.HasConstructorConstraint) ||
(typeParameter1.HasReferenceTypeConstraint != typeParameter2.HasReferenceTypeConstraint) ||
(typeParameter1.HasValueTypeConstraint != typeParameter2.HasValueTypeConstraint) ||
(typeParameter1.AllowByRefLike != typeParameter2.AllowByRefLike) ||
(typeParameter1.AllowsByRefLike != typeParameter2.AllowsByRefLike) ||
(typeParameter1.HasUnmanagedTypeConstraint != typeParameter2.HasUnmanagedTypeConstraint) ||
(typeParameter1.Variance != typeParameter2.Variance))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ public override bool HasValueTypeConstraint
}
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ ITypeParameterSymbol ITypeParameterSymbol.ReducedFrom

bool ITypeParameterSymbol.HasReferenceTypeConstraint => _underlying.HasReferenceTypeConstraint;

bool ITypeParameterSymbol.HasValueTypeConstraint => _underlying.HasValueTypeConstraint; // PROTOTYPE(RefStructInterfaces): Add AllowByRefLike to public API.
bool ITypeParameterSymbol.HasValueTypeConstraint => _underlying.HasValueTypeConstraint;

bool ITypeParameterSymbol.AllowsByRefLike => _underlying.AllowsByRefLike;

bool ITypeParameterSymbol.HasUnmanagedTypeConstraint => _underlying.HasUnmanagedTypeConstraint;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ ImmutableArray<SymbolDisplayPart> ITypeSymbol.ToMinimalDisplayParts(SemanticMode

SpecialType ITypeSymbol.SpecialType => UnderlyingTypeSymbol.SpecialType;

bool ITypeSymbol.IsRefLikeType => UnderlyingTypeSymbol.IsRefLikeType; // PROTOTYPE(RefStructInterfaces): adjust?
bool ITypeSymbol.IsRefLikeType => UnderlyingTypeSymbol.IsRefLikeType;

bool ITypeSymbol.IsReadOnly => UnderlyingTypeSymbol.IsReadOnly;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public override bool HasValueTypeConstraint
get { return false; }
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get { return false; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public override bool HasValueTypeConstraint
get { return false; }
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get { return false; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ public override bool HasValueTypeConstraint
}
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get
{
Expand Down Expand Up @@ -646,7 +646,7 @@ public override bool HasValueTypeConstraint
}
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get
{
Expand Down Expand Up @@ -909,12 +909,12 @@ public override bool HasValueTypeConstraint
}
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get
{
var typeParameter = this.OverriddenTypeParameter;
return ((object)typeParameter != null) && typeParameter.AllowByRefLike;
return ((object)typeParameter != null) && typeParameter.AllowsByRefLike;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal SynthesizedReadOnlyListTypeParameterSymbol(SynthesizedReadOnlyListTypeS

public override bool HasValueTypeConstraint => false;

public override bool AllowByRefLike => false; // The list is a class type and cannot store ref structs as elements.
public override bool AllowsByRefLike => false; // The list is a class type and cannot store ref structs as elements.

public override bool IsValueTypeFromConstraintTypes => false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ internal InlineArrayTypeParameterSymbol(SynthesizedInlineArrayTypeSymbol contain

public override bool HasValueTypeConstraint => false;

public override bool AllowByRefLike => false; // Span types do not support ref like type parameters for now
public override bool AllowsByRefLike => false; // Span types do not support ref like type parameters for now

public override bool IsValueTypeFromConstraintTypes => false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public override bool HasValueTypeConstraint
get { return false; }
}

public override bool AllowByRefLike
public override bool AllowsByRefLike
{
get { return false; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ internal sealed override ObsoleteAttributeData ObsoleteAttributeData

public abstract bool HasValueTypeConstraint { get; }

public abstract bool AllowByRefLike { get; }
public abstract bool AllowsByRefLike { get; }

public abstract bool IsValueTypeFromConstraintTypes { get; }

Expand Down

0 comments on commit 319fc7c

Please sign in to comment.