From 6f86aad70b336211b2918a2b0f8e29c322cd456e Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Fri, 3 May 2024 11:59:29 -0700 Subject: [PATCH 1/2] Add public API for ref like type parameters --- .../Portable/Binder/Binder_Expressions.cs | 2 +- .../Portable/Binder/Binder_Operators.cs | 8 +- .../Portable/Binder/ForEachLoopBinder.cs | 2 +- .../Semantics/Conversions/ConversionsBase.cs | 18 +-- .../BinaryOperatorOverloadResolution.cs | 6 +- .../CSharp/Portable/CodeGen/EmitOperators.cs | 2 +- .../EditAndContinue/CSharpSymbolMatcher.cs | 2 +- .../Model/TypeParameterSymbolAdapter.cs | 2 +- .../Emitter/NoPia/EmbeddedTypeParameter.cs | 2 +- .../LocalStateTracingInstrumenter.cs | 2 +- .../Lowering/SyntheticBoundNodeFactory.cs | 2 +- .../SymbolDisplayVisitor.Members.cs | 2 +- .../AnonymousType.TypeParameterSymbol.cs | 2 +- .../CSharp/Portable/Symbols/AssemblySymbol.cs | 5 +- .../Portable/Symbols/ConstraintsHelper.cs | 4 +- ...rrorTypeSymbol.ErrorTypeParameterSymbol.cs | 2 +- .../Symbols/MemberSignatureComparer.cs | 2 +- .../Metadata/PE/PETypeParameterSymbol.cs | 2 +- .../PublicModel/TypeParameterSymbol.cs | 4 +- .../Symbols/PublicModel/TypeSymbol.cs | 2 +- .../Symbols/Source/CrefTypeParameterSymbol.cs | 2 +- .../Source/IndexedTypeParameterSymbol.cs | 2 +- .../Source/SourceTypeParameterSymbol.cs | 8 +- ...thesizedReadOnlyListTypeParameterSymbol.cs | 2 +- .../SynthesizedInlineArrayTypeSymbol.cs | 2 +- ...thesizedSimpleMethodTypeParameterSymbol.cs | 2 +- .../Portable/Symbols/TypeParameterSymbol.cs | 2 +- .../Portable/Symbols/TypeSymbolExtensions.cs | 2 +- .../Wrapped/WrappedTypeParameterSymbol.cs | 4 +- .../Test/Emit3/RefStructInterfacesTests.cs | 116 +++++++++--------- .../Core/Portable/PublicAPI.Unshipped.txt | 2 + .../Core/Portable/RuntimeCapability.cs | 7 +- .../Portable/Symbols/ITypeParameterSymbol.cs | 5 + .../Portable/Symbols/AssemblySymbol.vb | 11 ++ .../Portable/Symbols/TypeParameterSymbol.vb | 6 + ...alysis.VisualBasic.Symbol.UnitTests.vbproj | 3 +- .../SymbolsTests/RefStructInterfacesTests.vb | 28 +++++ .../Symbols/EETypeParameterSymbol.cs | 4 +- .../Symbols/SimpleTypeParameterSymbol.cs | 2 +- 39 files changed, 175 insertions(+), 108 deletions(-) create mode 100644 src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 08444ccedc956..dea4422c89350 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -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); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index c14700e1bca8f..47b0b7ebed6b0 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -3570,20 +3570,20 @@ internal static ConstantValue GetIsOperatorConstantResult( // 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; } } @@ -3591,7 +3591,7 @@ internal static ConstantValue GetIsOperatorConstantResult( { if (targetType is TypeParameterSymbol) { - Debug.Assert(targetType is TypeParameterSymbol { AllowByRefLike: false }); + Debug.Assert(targetType is TypeParameterSymbol { AllowsByRefLike: false }); return ConstantValue.False; } } diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs index 3e13564f25b05..9110958219f83 100644 --- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs @@ -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); } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs index 8ba2482f27027..1542c185869b0 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs @@ -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; @@ -2849,7 +2849,7 @@ private bool HasImplicitReferenceTypeParameterConversion(TypeParameterSymbol sou return false; // Not a reference conversion. } - if (source.AllowByRefLike) + if (source.AllowsByRefLike) { return false; } @@ -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; @@ -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) { @@ -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; } @@ -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; @@ -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; } @@ -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; } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs index 566f3d31b106f..241efd53346a6 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs @@ -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()); @@ -776,7 +776,7 @@ static bool isUtf8ByteRepresentation(BoundExpression value) Conversion getOperandConversionForAllowByRefLikeNullCheck(bool isChecked, BoundExpression operand, TypeSymbol objectType, ref CompoundUseSiteInfo 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); } } diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs index b2bf6671a5f46..5b128036a5fb7 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs @@ -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' diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs index 719cb77bdec62..0f417c9677c43 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs @@ -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); diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs index cff33f3a4cdb3..0414f538311d9 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs @@ -306,7 +306,7 @@ bool Cci.IGenericParameter.AllowByRefLike { get { - return AdaptedTypeParameterSymbol.AllowByRefLike; + return AdaptedTypeParameterSymbol.AllowsByRefLike; } } diff --git a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedTypeParameter.cs b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedTypeParameter.cs index 8b15a1ace4d7f..8b6f1d8d8db3c 100644 --- a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedTypeParameter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedTypeParameter.cs @@ -49,7 +49,7 @@ protected override bool AllowByRefLike { get { - return UnderlyingTypeParameter.AdaptedTypeParameterSymbol.AllowByRefLike; + return UnderlyingTypeParameter.AdaptedTypeParameterSymbol.AllowsByRefLike; } } diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/LocalStateTracingInstrumenter.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/LocalStateTracingInstrumenter.cs index 1a5df922c5c68..f68c526d6e401 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/LocalStateTracingInstrumenter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/LocalStateTracingInstrumenter.cs @@ -236,7 +236,7 @@ _ when !variableType.IsManagedTypeNoUseSiteDiagnostics => 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 diff --git a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs index 67c1f0f491db8..4de6b7382d7ce 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs @@ -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; } diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs index a6aa4f0cb8909..d3bd5a9c66078 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs @@ -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(); diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs index b67c76698a31a..282fae7bca1e7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs @@ -91,7 +91,7 @@ public override bool HasValueTypeConstraint get { return false; } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs index 30b8c281ab36b..104e87e6513b5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs @@ -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; @@ -480,9 +482,8 @@ internal bool RuntimeSupportsInlineArrayTypes /// /// Figure out if the target runtime supports inline array types. /// - 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 { diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index 5d5807f143824..fd1ce627516e8 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -94,7 +94,7 @@ public static TypeParameterBounds ResolveBounds( diagnosticsBuilder.Free(); - if (typeParameter.AllowByRefLike) + if (typeParameter.AllowsByRefLike) { if (inherited) { @@ -936,7 +936,7 @@ private static bool CheckBasicConstraints( if (typeArgument.Type.IsRefLikeTypeOrAllowsByRefLike()) { - if (typeParameter.AllowByRefLike) + if (typeParameter.AllowsByRefLike) { if (args.CurrentCompilation.SourceModule != typeParameter.ContainingModule) { diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs index ae5a0e9b99f79..b267428c8eb6c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs @@ -91,7 +91,7 @@ public override bool HasValueTypeConstraint } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs b/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs index 909d2f982cddb..94b19e838e2a6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs @@ -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)) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs index 26a20e452ff33..419b2f0ccaf23 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs @@ -567,7 +567,7 @@ public override bool HasValueTypeConstraint } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeParameterSymbol.cs index 7b0f902faf283..f86c776fd9b7a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeParameterSymbol.cs @@ -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; diff --git a/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeSymbol.cs index 06a4a12f60719..476a5444dc0df 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PublicModel/TypeSymbol.cs @@ -168,7 +168,7 @@ ImmutableArray 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; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs index 752fdec9e3437..11e0068d37750 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs @@ -127,7 +127,7 @@ public override bool HasValueTypeConstraint get { return false; } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { return false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs index 550eb8f2e9754..b8dcede27477f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs @@ -142,7 +142,7 @@ public override bool HasValueTypeConstraint get { return false; } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { return false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs index 25cf7b67f0078..85572d48fc41e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs @@ -504,7 +504,7 @@ public override bool HasValueTypeConstraint } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { @@ -646,7 +646,7 @@ public override bool HasValueTypeConstraint } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { @@ -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; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeParameterSymbol.cs index 2ab8568fe8c03..f7db81e506fab 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeParameterSymbol.cs @@ -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; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs index 7dfc1895aa74d..3aba6e12c7b39 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs @@ -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; diff --git a/src/Compilers/CSharp/Portable/Symbols/SynthesizedSimpleMethodTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SynthesizedSimpleMethodTypeParameterSymbol.cs index 3d025fddc1307..cb49f133faacc 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SynthesizedSimpleMethodTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SynthesizedSimpleMethodTypeParameterSymbol.cs @@ -68,7 +68,7 @@ public override bool HasValueTypeConstraint get { return false; } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { return false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs index c8b43c2304489..e1985a785c8e0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs @@ -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; } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index 0fd16914f5a12..96c7f452714b5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -534,7 +534,7 @@ internal static bool IsErrorTypeOrIsRefLikeTypeOrAllowsByRefLike(this TypeSymbol internal static bool IsRefLikeTypeOrAllowsByRefLike(this TypeSymbol type) { - return type is { IsRefLikeType: true } or TypeParameterSymbol { AllowByRefLike: true }; + return type is { IsRefLikeType: true } or TypeParameterSymbol { AllowsByRefLike: true }; } private static readonly string[] s_expressionsNamespaceName = { "Expressions", "Linq", MetadataHelpers.SystemString, "" }; diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs index 4a4b906de6ed4..bf95d703024d0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs @@ -117,11 +117,11 @@ public override bool HasValueTypeConstraint } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { - return _underlyingTypeParameter.AllowByRefLike; + return _underlyingTypeParameter.AllowsByRefLike; } } diff --git a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs index d91e81699b621..bae5c77df2c82 100644 --- a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs @@ -2441,6 +2441,8 @@ void lambdaContainer() var comp = CreateCompilation(source, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics); comp.VerifyDiagnostics(); + + Assert.True(comp.SupportsRuntimeCapability(RuntimeCapability.ByRefLikeGenerics)); } // This is a clone of ReturnRefToRefStruct_ValEscape_01 from RefFieldTests.cs @@ -4373,10 +4375,12 @@ void verify(ModuleSymbol m) Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); + Assert.True(t.GetPublicSymbol().AllowsByRefLike); } - CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); + comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); + Assert.True(comp.SupportsRuntimeCapability(RuntimeCapability.ByRefLikeGenerics)); CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, parseOptions: TestOptions.Regular12).VerifyDiagnostics( // (3,22): error CS8652: The feature 'ref struct interfaces' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. @@ -4384,11 +4388,12 @@ void verify(ModuleSymbol m) Diagnostic(ErrorCode.ERR_FeatureInPreview, "ref struct").WithArguments("ref struct interfaces").WithLocation(3, 22) ); - CreateCompilation(src, targetFramework: TargetFramework.DesktopLatestExtended, parseOptions: TestOptions.RegularNext).VerifyDiagnostics( + comp = CreateCompilation(src, targetFramework: TargetFramework.DesktopLatestExtended, parseOptions: TestOptions.RegularNext).VerifyDiagnostics( // (3,22): error CS9500: Target runtime doesn't support by-ref-like generics. // where T : allows ref struct Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportByRefLikeGenerics, "ref struct").WithLocation(3, 22) ); + Assert.False(comp.SupportsRuntimeCapability(RuntimeCapability.ByRefLikeGenerics)); } [Fact] @@ -4415,7 +4420,7 @@ void verify(ModuleSymbol m) Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); @@ -4468,7 +4473,7 @@ public class D Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); var d = comp.SourceModule.GlobalNamespace.GetMember("D"); var dt = d.TypeParameters.Single(); @@ -4476,7 +4481,7 @@ public class D Assert.False(dt.HasValueTypeConstraint); Assert.False(dt.HasUnmanagedTypeConstraint); Assert.False(dt.HasNotNullConstraint); - Assert.True(dt.AllowByRefLike); + Assert.True(dt.AllowsByRefLike); } [Fact] @@ -4502,7 +4507,7 @@ public class C Assert.False(ct.HasValueTypeConstraint); Assert.False(ct.HasUnmanagedTypeConstraint); Assert.False(ct.HasNotNullConstraint); - Assert.True(ct.AllowByRefLike); + Assert.True(ct.AllowsByRefLike); } [Fact] @@ -4531,7 +4536,7 @@ public class C Assert.True(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4553,7 +4558,7 @@ public class C Assert.True(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4585,7 +4590,7 @@ public class C Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4611,7 +4616,7 @@ public class C Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4643,7 +4648,7 @@ public class C Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4678,7 +4683,7 @@ public void M() Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4715,7 +4720,7 @@ public virtual void M() Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4741,7 +4746,7 @@ public class C Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4770,7 +4775,7 @@ public void M() Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4807,7 +4812,7 @@ public virtual void M() Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4836,7 +4841,7 @@ public class C Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4858,7 +4863,7 @@ public class C Assert.True(t.HasValueTypeConstraint); Assert.True(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4887,7 +4892,7 @@ public class C Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.True(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4909,7 +4914,7 @@ public class C Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.True(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4940,7 +4945,7 @@ public interface I1 {} Assert.Equal("I1", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString()); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4967,7 +4972,7 @@ public interface I1 {} Assert.Equal("I1", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString()); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -4998,7 +5003,7 @@ public class C1 {} Assert.Equal("C1", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString()); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5027,7 +5032,7 @@ public class C Assert.Empty(t.ConstraintTypesNoUseSiteDiagnostics); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5052,7 +5057,7 @@ public class C Assert.Equal("System.Enum", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString()); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5079,7 +5084,7 @@ public class C Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); Assert.True(t.HasConstructorConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5102,7 +5107,7 @@ public class C Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); Assert.True(t.HasConstructorConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5123,7 +5128,7 @@ partial class C where T : allows ref struct var c = comp.SourceModule.GlobalNamespace.GetMember("C"); var t = c.TypeParameters.Single(); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5144,7 +5149,7 @@ partial class C where T : allows ref struct var c = comp.SourceModule.GlobalNamespace.GetMember("C"); var t = c.TypeParameters.Single(); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5165,7 +5170,7 @@ partial class C var c = comp.SourceModule.GlobalNamespace.GetMember("C"); var t = c.TypeParameters.Single(); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5190,7 +5195,7 @@ partial class C where T : struct, allows ref struct var c = comp.SourceModule.GlobalNamespace.GetMember("C"); var t = c.TypeParameters.Single(); - Assert.False(t.AllowByRefLike); + Assert.False(t.AllowsByRefLike); } [Fact] @@ -5215,7 +5220,7 @@ partial class C where T : struct var c = comp.SourceModule.GlobalNamespace.GetMember("C"); var t = c.TypeParameters.Single(); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5240,7 +5245,7 @@ partial void M() where T : allows ref struct var method = comp.SourceModule.GlobalNamespace.GetMember("C.M"); var t = method.TypeParameters.Single(); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5269,7 +5274,7 @@ partial void M() where T : allows ref struct var method = comp.SourceModule.GlobalNamespace.GetMember("C.M"); var t = method.TypeParameters.Single(); - Assert.False(t.AllowByRefLike); + Assert.False(t.AllowsByRefLike); } [Fact] @@ -5298,7 +5303,7 @@ partial void M() var method = comp.SourceModule.GlobalNamespace.GetMember("C.M"); var t = method.TypeParameters.Single(); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5327,7 +5332,7 @@ partial void M() where T : struct, allows ref struct var method = comp.SourceModule.GlobalNamespace.GetMember("C.M"); var t = method.TypeParameters.Single(); - Assert.False(t.AllowByRefLike); + Assert.False(t.AllowsByRefLike); } [Fact] @@ -5356,7 +5361,7 @@ partial void M() where T : struct var method = comp.SourceModule.GlobalNamespace.GetMember("C.M"); var t = method.TypeParameters.Single(); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); } [Fact] @@ -5400,7 +5405,7 @@ public override void M2() where T : unmanaged var method1 = comp.SourceModule.GlobalNamespace.GetMember("C2.M1"); var t1 = method1.TypeParameters.Single(); - Assert.True(t1.AllowByRefLike); + Assert.True(t1.AllowsByRefLike); var method2 = comp.SourceModule.GlobalNamespace.GetMember("C3.M2"); var t2 = method2.TypeParameters.Single(); @@ -5439,7 +5444,7 @@ public override void M2() var method1 = comp1.SourceModule.GlobalNamespace.GetMember("C2.M1"); var t1 = method1.TypeParameters.Single(); - Assert.True(t1.AllowByRefLike); + Assert.True(t1.AllowsByRefLike); var method2 = comp1.SourceModule.GlobalNamespace.GetMember("C2.M2"); var t2 = method2.TypeParameters.Single(); @@ -5494,7 +5499,7 @@ class C {} var method1 = comp.SourceModule.GlobalNamespace.GetMember("C2.M1"); var t1 = method1.TypeParameters.Single(); - Assert.True(t1.AllowByRefLike); + Assert.True(t1.AllowsByRefLike); Assert.Equal("C", t1.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString()); var method2 = comp.SourceModule.GlobalNamespace.GetMember("C2.M2"); @@ -5537,7 +5542,7 @@ void C1.M2() where T : unmanaged var method1 = comp.SourceModule.GlobalNamespace.GetMember("C2.C1.M1"); var t1 = method1.TypeParameters.Single(); - Assert.True(t1.AllowByRefLike); + Assert.True(t1.AllowsByRefLike); var method2 = comp.SourceModule.GlobalNamespace.GetMember("C2.C1.M2"); var t2 = method2.TypeParameters.Single(); @@ -5572,7 +5577,7 @@ void C1.M2() var method1 = comp1.SourceModule.GlobalNamespace.GetMember("C2.C1.M1"); var t1 = method1.TypeParameters.Single(); - Assert.True(t1.AllowByRefLike); + Assert.True(t1.AllowsByRefLike); var method2 = comp1.SourceModule.GlobalNamespace.GetMember("C2.C1.M2"); var t2 = method2.TypeParameters.Single(); @@ -5623,7 +5628,7 @@ class C {} var method1 = comp.SourceModule.GlobalNamespace.GetMember("C2.C1.M1"); var t1 = method1.TypeParameters.Single(); - Assert.True(t1.AllowByRefLike); + Assert.True(t1.AllowsByRefLike); Assert.Equal("C", t1.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString()); var method2 = comp.SourceModule.GlobalNamespace.GetMember("C2.C1.M2"); @@ -5747,7 +5752,8 @@ void verify(ModuleSymbol m) Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.False(t.AllowByRefLike); + Assert.False(t.AllowsByRefLike); + Assert.False(t.GetPublicSymbol().AllowsByRefLike); } } @@ -5773,14 +5779,14 @@ void verify(ModuleSymbol m) Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); var u = c.TypeParameters[1]; Assert.False(u.HasReferenceTypeConstraint); Assert.False(u.HasValueTypeConstraint); Assert.False(u.HasUnmanagedTypeConstraint); Assert.False(u.HasNotNullConstraint); - Assert.True(u.AllowByRefLike); + Assert.True(u.AllowsByRefLike); } } @@ -5806,14 +5812,14 @@ void verify(ModuleSymbol m) Assert.False(t.HasValueTypeConstraint); Assert.False(t.HasUnmanagedTypeConstraint); Assert.False(t.HasNotNullConstraint); - Assert.True(t.AllowByRefLike); + Assert.True(t.AllowsByRefLike); var u = c.TypeParameters[1]; Assert.False(u.HasReferenceTypeConstraint); Assert.False(u.HasValueTypeConstraint); Assert.False(u.HasUnmanagedTypeConstraint); Assert.False(u.HasNotNullConstraint); - Assert.False(u.AllowByRefLike); + Assert.False(u.AllowsByRefLike); } } @@ -18040,7 +18046,7 @@ public void Add(int x){} void validate(ModuleSymbol m) { var p = m.GlobalNamespace.GetMember("Helper.Test1").Parameters[0]; - AssertEx.Equal("params scoped T x", p.ToTestDisplayString()); // PROTOTYPE(RefStructInterfaces): Adjust symbol display to drop "scoped" once we have a necessary public API to check for 'AllowsRefLike' + AssertEx.Equal("params T x", p.ToTestDisplayString()); Assert.Equal(ScopedKind.ScopedValue, p.EffectiveScope); p = m.GlobalNamespace.GetMember("Helper.Test2").Parameters[0]; @@ -18103,7 +18109,7 @@ public void Add(int x){} var lambdas = tree.GetRoot().DescendantNodes().OfType().ToArray(); var p = model.GetDeclaredSymbol(lambdas[0].ParameterList.Parameters[0]).GetSymbol(); - AssertEx.Equal("params scoped T x", p.ToTestDisplayString()); // PROTOTYPE(RefStructInterfaces): Adjust symbol display to drop "scoped" once we have a necessary public API to check for 'AllowsRefLike' + AssertEx.Equal("params T x", p.ToTestDisplayString()); Assert.Equal(ScopedKind.ScopedValue, p.EffectiveScope); p = model.GetDeclaredSymbol(lambdas[1].ParameterList.Parameters[0]).GetSymbol(); @@ -18714,7 +18720,7 @@ namespace System { foreach (var tp in m.ContainingAssembly.GetTypeByMetadataName("<>A`2").TypeParameters) { - Assert.True(tp.AllowByRefLike); + Assert.True(tp.AllowsByRefLike); } } ).VerifyDiagnostics(); @@ -18770,7 +18776,7 @@ namespace System { foreach (var tp in m.ContainingAssembly.GetTypeByMetadataName("<>F`2").TypeParameters) { - Assert.True(tp.AllowByRefLike); + Assert.True(tp.AllowsByRefLike); } } ).VerifyDiagnostics(); @@ -18917,7 +18923,7 @@ namespace System { foreach (var tp in m.ContainingAssembly.GetTypeByMetadataName("<>f__AnonymousDelegate0`1").TypeParameters) { - Assert.True(tp.AllowByRefLike); + Assert.True(tp.AllowsByRefLike); } } ).VerifyDiagnostics(); @@ -18966,7 +18972,7 @@ ref struct S2 {} { foreach (var tp in m.ContainingAssembly.GetTypeByMetadataName("<>f__AnonymousDelegate0`1").TypeParameters) { - Assert.False(tp.AllowByRefLike); + Assert.False(tp.AllowsByRefLike); } } ).VerifyDiagnostics(); diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index e5fe82d74f013..425f91b0fc85d 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -57,3 +57,5 @@ static Microsoft.CodeAnalysis.DocumentationCommentId.CreateDeclarationId(Microso [RSEXPERIMENTAL001]Microsoft.CodeAnalysis.SemanticModelOptions.DisableNullableAnalysis = 2 -> Microsoft.CodeAnalysis.SemanticModelOptions [RSEXPERIMENTAL001]Microsoft.CodeAnalysis.Compilation.GetSemanticModel(Microsoft.CodeAnalysis.SyntaxTree! syntaxTree, Microsoft.CodeAnalysis.SemanticModelOptions options) -> Microsoft.CodeAnalysis.SemanticModel! abstract Microsoft.CodeAnalysis.SemanticModel.NullableAnalysisIsDisabled.get -> bool +Microsoft.CodeAnalysis.ITypeParameterSymbol.AllowsByRefLike.get -> bool +Microsoft.CodeAnalysis.RuntimeCapability.ByRefLikeGenerics = 8 -> Microsoft.CodeAnalysis.RuntimeCapability diff --git a/src/Compilers/Core/Portable/RuntimeCapability.cs b/src/Compilers/Core/Portable/RuntimeCapability.cs index b1502cff4867c..21bb31cc1b23e 100644 --- a/src/Compilers/Core/Portable/RuntimeCapability.cs +++ b/src/Compilers/Core/Portable/RuntimeCapability.cs @@ -43,6 +43,11 @@ public enum RuntimeCapability /// /// Indicates that this version of runtime supports inline array types. /// - InlineArrayTypes = 7 + InlineArrayTypes = 7, + + /// + /// Indicates that this version of runtime supports generic type parameters allowing substitution with a ref struct. + /// + ByRefLikeGenerics = 8, } } diff --git a/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs b/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs index 1ee93e8b5d76e..4b9b0241a53e2 100644 --- a/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs +++ b/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs @@ -59,6 +59,11 @@ public interface ITypeParameterSymbol : ITypeSymbol /// bool HasValueTypeConstraint { get; } + /// + /// True if the 'allows ref struct' constraint was specified for the type parameter. + /// + bool AllowsByRefLike { get; } + /// /// True if the value type constraint (unmanaged) was specified for the type parameter. /// diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb index fa196d7309f64..3b5c52845c3b5 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb @@ -347,6 +347,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return Me.RuntimeSupportsVirtualStaticsInInterfaces Case RuntimeCapability.InlineArrayTypes Return Me.RuntimeSupportsInlineArrayTypes + Case RuntimeCapability.ByRefLikeGenerics + Return Me.RuntimeSupportsByRefLikeGenerics End Select Return False @@ -409,6 +411,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property + Private ReadOnly Property RuntimeSupportsByRefLikeGenerics As Boolean + Get + ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsByRefLikeGenerics + ' PROTOTYPE(RefStructInterfaces) Implement real check once RuntimeFeature.ByRefLikeGenerics becomes available in ref assembly. + ' See https://github.com/dotnet/runtime/issues/68002#issuecomment-1942166436 for details. + Return RuntimeSupportsInlineArrayTypes + End Get + End Property + Private Function RuntimeSupportsFeature(feature As SpecialMember) As Boolean Debug.Assert(SpecialMembers.GetDescriptor(feature).DeclaringSpecialType = SpecialType.System_Runtime_CompilerServices_RuntimeFeature) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb index 7f76621542b37..a0e9968ac2f62 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb @@ -317,6 +317,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public MustOverride ReadOnly Property HasValueTypeConstraint As Boolean Implements ITypeParameterSymbol.HasValueTypeConstraint + Public ReadOnly Property AllowsByRefLike As Boolean Implements ITypeParameterSymbol.AllowsByRefLike + Get + Return False ' PROTOTYPE(RefStructInterfaces): Implement for real + End Get + End Property + Private ReadOnly Property HasUnmanagedTypeConstraint As Boolean Implements ITypeParameterSymbol.HasUnmanagedTypeConstraint Get Return False diff --git a/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj b/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj index 72c9595f4978b..68d3126328503 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj +++ b/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj @@ -16,9 +16,10 @@ - + + diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb new file mode 100644 index 0000000000000..e3a04faf75c60 --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/RefStructInterfacesTests.vb @@ -0,0 +1,28 @@ +' Licensed to the .NET Foundation under one or more agreements. +' The .NET Foundation licenses this file to you under the MIT license. +' See the LICENSE file in the project root for more information. + +Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic.Symbols +Imports Roslyn.Test.Utilities + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests + + Public Class RefStructInterfacesTests + Inherits BasicTestBase + + ' PROTOTYPE(RefStructInterfaces): Switch to supporting target framework once we have its ref assemblies. + Private Shared ReadOnly s_targetFrameworkSupportingByRefLikeGenerics As TargetFramework = TargetFramework.Net80 + + + Public Sub RuntimeCapability_01() + + Dim comp = CreateCompilation("", targetFramework:=s_targetFrameworkSupportingByRefLikeGenerics) + Assert.True(comp.SupportsRuntimeCapability(RuntimeCapability.ByRefLikeGenerics)) + + comp = CreateCompilation("", targetFramework:=TargetFramework.DesktopLatestExtended) + Assert.False(comp.SupportsRuntimeCapability(RuntimeCapability.ByRefLikeGenerics)) + End Sub + End Class +End Namespace + diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs index a4428d556b8bb..fb83007f72a94 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs @@ -95,9 +95,9 @@ public override bool HasValueTypeConstraint get { return _sourceTypeParameter.HasValueTypeConstraint; } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { - get { return _sourceTypeParameter.AllowByRefLike; } + get { return _sourceTypeParameter.AllowsByRefLike; } } public override bool IsValueTypeFromConstraintTypes diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs index fe8ee4f971be1..5ed89caf65d15 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs @@ -77,7 +77,7 @@ public override bool HasValueTypeConstraint get { return false; } } - public override bool AllowByRefLike + public override bool AllowsByRefLike { get { return false; } } From c3ff22ae8247970eb63fda2cdf83fb4041808c0d Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Sat, 4 May 2024 16:21:05 -0700 Subject: [PATCH 2/2] Fixup --- .../CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs index 28aeb52683796..3d6b57a175230 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs @@ -27,6 +27,7 @@ internal class CodeGenerationTypeParameterSymbol( public bool HasConstructorConstraint { get; } = hasConstructorConstraint; public bool HasReferenceTypeConstraint { get; } = hasReferenceConstraint; public bool HasValueTypeConstraint { get; } = hasValueConstraint; + public bool AllowsByRefLike => false; public bool HasUnmanagedTypeConstraint { get; } = hasUnmanagedConstraint; public bool HasNotNullConstraint { get; } = hasNotNullConstraint; public int Ordinal { get; } = ordinal;