From 3735f11e4496dc2ce2325c02797d570983779440 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 10 Jan 2019 11:20:38 -0800 Subject: [PATCH] Add ITypeSymbol.IsUnmanagedType and ITypeSymbol.IsRefLikeType (#32277) * Add ITypeSymbol.IsUnmanagedType and ITypeSymbol.IsRefLikeType Fixes #30427 and #30426 --- .../Portable/Binder/Binder.ValueChecks.cs | 22 +++--- .../Portable/Binder/Binder_Expressions.cs | 2 +- .../CSharp/Portable/Binder/Binder_Patterns.cs | 2 +- .../Portable/Binder/Binder_Statements.cs | 4 +- .../Semantics/Conversions/Conversions.cs | 2 +- .../Portable/Binder/UsingStatementBinder.cs | 2 +- .../Portable/FlowAnalysis/NullableWalker.cs | 2 +- .../SymbolDisplayVisitor.Types.cs | 2 +- .../AnonymousType.TypePublicSymbol.cs | 2 +- .../AnonymousType.TemplateSymbol.cs | 2 +- .../Portable/Symbols/ArrayTypeSymbol.cs | 2 +- .../Portable/Symbols/DynamicTypeSymbol.cs | 2 +- .../Portable/Symbols/ErrorTypeSymbol.cs | 2 +- .../Symbols/Metadata/PE/PENamedTypeSymbol.cs | 8 +- .../Portable/Symbols/PointerTypeSymbol.cs | 2 +- .../Source/SourceMemberContainerSymbol.cs | 4 +- .../Symbols/Source/SourceMemberFieldSymbol.cs | 2 +- .../Symbols/Source/SourceNamedTypeSymbol.cs | 2 +- .../Source/SourceNamedTypeSymbol_Bases.cs | 2 +- .../Symbols/Source/SourcePropertySymbol.cs | 2 +- .../Synthesized/SynthesizedContainer.cs | 2 +- .../SynthesizedEmbeddedAttributeSymbol.cs | 2 +- .../Portable/Symbols/TypeParameterSymbol.cs | 2 +- .../CSharp/Portable/Symbols/TypeSymbol.cs | 4 +- .../Portable/Symbols/TypeSymbolExtensions.cs | 2 +- .../Symbols/Wrapped/WrappedNamedTypeSymbol.cs | 4 +- .../Attributes/AttributeTests_IsByRefLike.cs | 8 +- .../Semantic/Semantics/RefEscapingTests.cs | 56 +++++++++++++ .../Test/Semantic/Semantics/UnsafeTests.cs | 65 ++++++++++++++++ .../SymbolDisplay/SymbolDisplayTests.cs | 4 + .../Symbol/Symbols/MockNamedTypeSymbol.cs | 2 +- .../Test/Syntax/Parsing/ReadOnlyStructs.cs | 26 +++---- .../Core/Portable/PublicAPI.Unshipped.txt | 2 + .../Core/Portable/Symbols/ITypeSymbol.cs | 16 ++++ .../Test/Utilities/CSharp/CSharpTestBase.cs | 16 ++++ .../Portable/Symbols/TypeSymbol.vb | 14 ++++ .../Compilation/SemanticModelAPITests.vb | 78 +++++++++++++++++++ .../Symbols/EENamedTypeSymbol.cs | 2 +- ...aAsSourceService.WrappedNamedTypeSymbol.cs | 4 + .../CodeGenerationAbstractNamedTypeSymbol.cs | 7 +- .../Symbols/CodeGenerationTypeSymbol.cs | 4 + 41 files changed, 328 insertions(+), 62 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs index e921968c60a..1585d14568c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs @@ -1145,7 +1145,7 @@ bool isRefEscape } // check receiver if ref-like - if (receiverOpt?.Type?.IsByRefLikeType == true) + if (receiverOpt?.Type?.IsRefLikeType == true) { escapeScope = Math.Max(escapeScope, GetValEscape(receiverOpt, scopeOfTheContainingExpression)); } @@ -1261,7 +1261,7 @@ bool isRefEscape } // check receiver if ref-like - if (receiverOpt?.Type?.IsByRefLikeType == true) + if (receiverOpt?.Type?.IsRefLikeType == true) { return CheckValEscape(receiverOpt.Syntax, receiverOpt, escapeFrom, escapeTo, false, diagnostics); } @@ -1294,7 +1294,7 @@ bool isRefEscape // collect all writeable ref-like arguments, including receiver var receiverType = receiverOpt?.Type; - if (receiverType?.IsByRefLikeType == true && receiverType?.IsReadOnly == false) + if (receiverType?.IsRefLikeType == true && receiverType?.IsReadOnly == false) { escapeTo = GetValEscape(receiverOpt, scopeOfTheContainingExpression); } @@ -1313,7 +1313,7 @@ bool isRefEscape } var paramIndex = argsToParamsOpt.IsDefault ? argIndex : argsToParamsOpt[argIndex]; - if (parameters[paramIndex].RefKind.IsWritableReference() && argument.Type?.IsByRefLikeType == true) + if (parameters[paramIndex].RefKind.IsWritableReference() && argument.Type?.IsRefLikeType == true) { escapeTo = Math.Min(escapeTo, GetValEscape(argument, scopeOfTheContainingExpression)); } @@ -1328,7 +1328,7 @@ bool isRefEscape { var argument = argListArgs[argIndex]; var refKind = argListRefKindsOpt.IsDefault ? RefKind.None : argListRefKindsOpt[argIndex]; - if (refKind.IsWritableReference() && argument.Type?.IsByRefLikeType == true) + if (refKind.IsWritableReference() && argument.Type?.IsRefLikeType == true) { escapeTo = Math.Min(escapeTo, GetValEscape(argument, scopeOfTheContainingExpression)); } @@ -1387,7 +1387,7 @@ bool isRefEscape // They have "outer" val escape, so cannot be worse than escapeTo. // check val escape of receiver if ref-like - if (receiverOpt?.Type?.IsByRefLikeType == true) + if (receiverOpt?.Type?.IsRefLikeType == true) { return CheckValEscape(receiverOpt.Syntax, receiverOpt, scopeOfTheContainingExpression, escapeTo, false, diagnostics); } @@ -1448,7 +1448,7 @@ private static ParameterSymbol TryGetunmatchedInParameterAndFreeMatchedArgs(Immu if (parameter.RefKind == RefKind.In && inParametersMatchedWithArgs?[i] != true && - parameter.Type.TypeSymbol.IsByRefLikeType == false) + parameter.Type.TypeSymbol.IsRefLikeType == false) { return parameter; } @@ -2157,7 +2157,7 @@ internal static uint GetValEscape(BoundExpression expr, uint scopeOfTheContainin } // to have local-referring values an expression must have a ref-like type - if (expr.Type?.IsByRefLikeType != true) + if (expr.Type?.IsRefLikeType != true) { return Binder.ExternalScope; } @@ -2227,7 +2227,7 @@ internal static uint GetValEscape(BoundExpression expr, uint scopeOfTheContainin var fieldAccess = (BoundFieldAccess)expr; var fieldSymbol = fieldAccess.FieldSymbol; - if (fieldSymbol.IsStatic || !fieldSymbol.ContainingType.IsByRefLikeType) + if (fieldSymbol.IsStatic || !fieldSymbol.ContainingType.IsRefLikeType) { // Already an error state. return Binder.ExternalScope; @@ -2454,7 +2454,7 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint } // to have local-referring values an expression must have a ref-like type - if (expr.Type?.IsByRefLikeType != true) + if (expr.Type?.IsRefLikeType != true) { return true; } @@ -2534,7 +2534,7 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint var fieldAccess = (BoundFieldAccess)expr; var fieldSymbol = fieldAccess.FieldSymbol; - if (fieldSymbol.IsStatic || !fieldSymbol.ContainingType.IsByRefLikeType) + if (fieldSymbol.IsStatic || !fieldSymbol.ContainingType.IsRefLikeType) { // Already an error state. return true; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index adc8b01ea7d..1547b6856a5 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1444,7 +1444,7 @@ private BoundExpression SynthesizeMethodGroupReceiver(CSharpSyntaxNode syntax, A private bool IsBadLocalOrParameterCapture(Symbol symbol, TypeSymbol type, RefKind refKind) { - if (refKind != RefKind.None || type.IsByRefLikeType) + if (refKind != RefKind.None || type.IsRefLikeType) { var containingMethod = this.ContainingMemberOrLambda as MethodSymbol; if ((object)containingMethod != null && (object)symbol.ContainingSymbol != (object)containingMethod) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index 987bae0962b..31e33407126 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -450,7 +450,7 @@ private BoundPattern BindDiscardPattern(DiscardPatternSyntax node, TypeSymbol in /// private static uint GetValEscape(TypeSymbol type, uint possibleValEscape) { - return type.IsByRefLikeType ? possibleValEscape : Binder.ExternalScope; + return type.IsRefLikeType ? possibleValEscape : Binder.ExternalScope; } TypeSymbol BindRecursivePatternType( diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 860c60e3978..91f36cb7ef7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -677,7 +677,7 @@ internal MethodSymbol TryFindDisposePatternMethod(BoundExpression expr, SyntaxNo { Debug.Assert(!(expr is null)); Debug.Assert(!(expr.Type is null)); - Debug.Assert(expr.Type.IsValueType && expr.Type.IsByRefLikeType); // pattern dispose lookup is only valid on ref structs + Debug.Assert(expr.Type.IsValueType && expr.Type.IsRefLikeType); // pattern dispose lookup is only valid on ref structs // Don't try and lookup if we're not enabled if (MessageID.IDS_FeatureUsingDeclarations.RequiredVersion() > Compilation.LanguageVersion) @@ -1397,7 +1397,7 @@ private BoundExpression InferTypeForDiscardAssignment(BoundDiscardExpression op1 } } - if (op1.Type.IsByRefLikeType) + if (op1.Type.IsRefLikeType) { var leftEscape = GetValEscape(op1, LocalScopeDepth); op2 = ValidateEscape(op2, leftEscape, isByRef: false, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index 12d1306ada3..db5f0c865b4 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -319,7 +319,7 @@ public override Conversion GetStackAllocConversion(BoundStackAllocArrayCreation else { var spanType = _binder.GetWellKnownType(WellKnownType.System_Span_T, ref useSiteDiagnostics); - if (spanType.TypeKind == TypeKind.Struct && spanType.IsByRefLikeType) + if (spanType.TypeKind == TypeKind.Struct && spanType.IsRefLikeType) { var spanType_T = spanType.Construct(sourceExpression.ElementType); var spanConversion = ClassifyImplicitConversionFromType(spanType_T, destination, ref useSiteDiagnostics); diff --git a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs index 06c47b9fd33..ab9b80fb070 100644 --- a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs @@ -162,7 +162,7 @@ bool populateDisposableConversionOrDisposeMethod(bool fromExpression) // If this is a ref struct, try binding via pattern. // We won't need to try and bind a second time if it fails, as async dispose can't be pattern based (ref structs are not allowed in async methods) - if (!(type is null) && type.IsValueType && type.IsByRefLikeType) + if (!(type is null) && type.IsValueType && type.IsRefLikeType) { BoundExpression receiver = fromExpression ? expressionOpt diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index c71d82c1ab2..e2463f7918c 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -4971,7 +4971,7 @@ private void SetUnknownResultNullability() public override BoundNode VisitStackAllocArrayCreation(BoundStackAllocArrayCreation node) { var result = base.VisitStackAllocArrayCreation(node); - Debug.Assert((object)node.Type == null || node.Type.IsPointerType() || node.Type.IsByRefLikeType); + Debug.Assert((object)node.Type == null || node.Type.IsPointerType() || node.Type.IsRefLikeType); SetResult(node); return result; } diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index 0cc18d2da25..4943fbb7402 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -651,7 +651,7 @@ private void AddTypeKind(INamedTypeSymbol symbol) AddSpace(); } - if (csharpType.IsByRefLikeType) + if (csharpType.IsRefLikeType) { AddKeyword(SyntaxKind.RefKeyword); AddSpace(); diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs index 71e31de248d..906b1b3fe34 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs @@ -173,7 +173,7 @@ public override bool IsAbstract get { return false; } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { return false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs index cae319dedcb..583e31391f3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs @@ -288,7 +288,7 @@ public override bool IsAbstract get { return false; } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { return false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs index 850e076aecf..e1c52c24b60 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs @@ -228,7 +228,7 @@ internal sealed override bool IsManagedType } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs index 8f00ff8aa50..f73de1340b4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs @@ -112,7 +112,7 @@ internal sealed override bool IsManagedType } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index 018e432b018..e181109b5b3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs @@ -103,7 +103,7 @@ public sealed override bool IsValueType get { return false; } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index 5df78703df6..b3b80c85871 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -629,13 +629,13 @@ public override ImmutableArray GetAttributes() MightContainExtensionMethods ? AttributeDescription.CaseSensitiveExtensionAttribute : default, out _, // Filter out [Obsolete], unless it was user defined - (IsByRefLikeType && ObsoleteAttributeData is null) ? AttributeDescription.ObsoleteAttribute : default, + (IsRefLikeType && ObsoleteAttributeData is null) ? AttributeDescription.ObsoleteAttribute : default, out _, // Filter out [IsReadOnly] IsReadOnly ? AttributeDescription.IsReadOnlyAttribute : default, out _, // Filter out [IsByRefLike] - IsByRefLikeType ? AttributeDescription.IsByRefLikeAttribute : default); + IsRefLikeType ? AttributeDescription.IsByRefLikeAttribute : default); ImmutableInterlocked.InterlockedInitialize(ref uncommon.lazyCustomAttributes, loadedCustomAttributes); } @@ -2041,7 +2041,7 @@ public override bool IsSerializable get { return (_flags & TypeAttributes.Serializable) != 0; } } - internal override bool IsByRefLikeType + public override bool IsRefLikeType { get { @@ -2162,7 +2162,7 @@ internal override ObsoleteAttributeData ObsoleteAttributeData return null; } - bool ignoreByRefLikeMarker = this.IsByRefLikeType; + bool ignoreByRefLikeMarker = this.IsRefLikeType; ObsoleteAttributeHelpers.InitializeObsoleteDataFromMetadata(ref uncommon.lazyObsoleteAttributeData, _handle, ContainingPEModule, ignoreByRefLikeMarker); return uncommon.lazyObsoleteAttributeData; } diff --git a/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs index 931cf2e487c..6b1e080a5d4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs @@ -107,7 +107,7 @@ internal sealed override bool IsManagedType } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 61a2e853df0..c7f7ffdf6bc 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -705,7 +705,7 @@ public override bool IsStatic } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { @@ -1404,7 +1404,7 @@ protected void AfterMembersChecks(DiagnosticBag diagnostics) CheckForUnmatchedOperators(diagnostics); var location = Locations[0]; - if (this.IsByRefLikeType) + if (this.IsRefLikeType) { this.DeclaringCompilation.EnsureIsByRefLikeAttributeExists(diagnostics, location, modifyCompilation: true); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index bb71cae01a4..021f0d37d92 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -55,7 +55,7 @@ protected void TypeChecks(TypeSymbol type, DiagnosticBag diagnostics) { diagnostics.Add(ErrorCode.ERR_FieldCantBeRefAny, TypeSyntax?.Location ?? this.Locations[0], type); } - else if (type.IsByRefLikeType && (this.IsStatic || !containingType.IsByRefLikeType)) + else if (type.IsRefLikeType && (this.IsStatic || !containingType.IsRefLikeType)) { diagnostics.Add(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, TypeSyntax?.Location ?? this.Locations[0], type); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index 6ecb226474c..59f6a7aa729 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -1161,7 +1161,7 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor)); } - if (this.IsByRefLikeType) + if (this.IsRefLikeType) { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsByRefLikeAttribute(this)); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs index 96d12bf6135..e04475220dd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs @@ -469,7 +469,7 @@ private static BaseListSyntax GetBaseListOpt(SingleTypeDeclaration decl) diagnostics.Add(ErrorCode.ERR_StaticClassInterfaceImpl, location, this, baseType); } - if (this.IsByRefLikeType) + if (this.IsRefLikeType) { // '{0}': ref structs cannot implement interfaces diagnostics.Add(ErrorCode.ERR_RefStructInterfaceImpl, location, this, baseType); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index bdd37b8e953..38a213ddd8b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -1415,7 +1415,7 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok { diagnostics.Add(ErrorCode.ERR_FieldCantBeRefAny, this.CSharpSyntaxNode.Type.Location, type); } - else if (this.IsAutoProperty && type.IsByRefLikeType && (this.IsStatic || !this.ContainingType.IsByRefLikeType)) + else if (this.IsAutoProperty && type.IsRefLikeType && (this.IsStatic || !this.ContainingType.IsRefLikeType)) { diagnostics.Add(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, this.CSharpSyntaxNode.Type.Location, type); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs index 104f764bd48..5ffc0d7dbaa 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs @@ -162,7 +162,7 @@ internal override IEnumerable GetFieldsToEmit() public override bool IsStatic => false; - internal sealed override bool IsByRefLikeType => false; + public sealed override bool IsRefLikeType => false; internal sealed override bool IsReadOnly => false; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs index 89b63fc7a6e..e031f3164a4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs @@ -118,7 +118,7 @@ private static NamedTypeSymbol MakeBaseType(CSharpCompilation compilation, Diagn public override bool IsStatic => false; - internal override bool IsByRefLikeType => false; + public override bool IsRefLikeType => false; internal override bool IsReadOnly => false; diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs index 6af80440700..b770aebb943 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs @@ -593,7 +593,7 @@ internal sealed override bool IsManagedType } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs index 2ffd4cf01e6..6256afb1963 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs @@ -634,6 +634,8 @@ public virtual NamedTypeSymbol TupleUnderlyingType /// internal abstract bool IsManagedType { get; } + bool ITypeSymbol.IsUnmanagedType => !IsManagedType; + internal bool NeedsNullableAttribute() { return TypeSymbolWithAnnotations.NeedsNullableAttribute(typeWithAnnotationsOpt: default, typeOpt: this); @@ -671,7 +673,7 @@ internal TypeSymbol SetSpeakableNullabilityForReferenceTypes() /// /// Returns true if the type may contain embedded references /// - internal abstract bool IsByRefLikeType { get; } + public abstract bool IsRefLikeType { get; } /// /// Returns true if the type is a readonly struct diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index 57d532ab344..3f23dedc75c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -1056,7 +1056,7 @@ internal static bool IsValidV6SwitchGoverningType(this TypeSymbol type, bool isT return ignoreSpanLikeTypes ? false : - type.IsByRefLikeType; + type.IsRefLikeType; } public static bool IsIntrinsicType(this TypeSymbol type) diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs index d182e18780c..a94bcce719e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs @@ -207,9 +207,9 @@ public override bool IsSerializable get { return _underlyingType.IsSerializable; } } - internal override bool IsByRefLikeType + public override bool IsRefLikeType { - get { return _underlyingType.IsByRefLikeType; } + get { return _underlyingType.IsRefLikeType; } } internal override bool IsReadOnly diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsByRefLike.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsByRefLike.cs index c699f7ac694..e42480aea71 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsByRefLike.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsByRefLike.cs @@ -657,7 +657,7 @@ class Test void validate(ModuleSymbol module) { var type = module.ContainingAssembly.GetTypeByMetadataName("Test").GetTypeMember("S1"); - Assert.True(type.IsByRefLikeType); + Assert.True(type.IsRefLikeType); var assemblyName = module.ContainingAssembly.Name; @@ -741,7 +741,7 @@ class Test CompileAndVerify(text, verify: Verification.Passes, symbolValidator: module => { var type = module.ContainingAssembly.GetTypeByMetadataName("Test").GetTypeMember("S1"); - Assert.True(type.IsByRefLikeType); + Assert.True(type.IsRefLikeType); var attribute = type.GetAttributes().Single(); Assert.Equal("Windows.Foundation.Metadata.DeprecatedAttribute", attribute.AttributeClass.ToDisplayString()); @@ -788,7 +788,7 @@ class Test CompileAndVerify(text, verify: Verification.Passes, symbolValidator: module => { var type = module.ContainingAssembly.GetTypeByMetadataName("Test").GetTypeMember("S1"); - Assert.True(type.IsByRefLikeType); + Assert.True(type.IsRefLikeType); var attributes = type.GetAttributes(); @@ -991,7 +991,7 @@ namespace System private static void AssertReferencedIsByRefLike(TypeSymbol type, bool hasObsolete = true) { var peType = (PENamedTypeSymbol)type; - Assert.True(peType.IsByRefLikeType); + Assert.True(peType.IsRefLikeType); // there is no [Obsolete] or [IsByRef] attribute returned Assert.Empty(peType.GetAttributes()); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs index 6345d0cf817..07202ea61a2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs @@ -12,6 +12,62 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics [CompilerTrait(CompilerFeature.ReadOnlyReferences)] public class RefEscapingTests : CompilingTestBase { + [Fact] + public void RefStructSemanticModel() + { + var tree = SyntaxFactory.ParseSyntaxTree(@" +using System; +struct S1 { } +ref struct S2 { public S1 F1; } +enum E1 { } +class C +{ + unsafe void M() where U : unmanaged + { + Span span = default; + var s1 = new S1(); + var s2 = new S2(); + var i0 = 0; + var e1 = new E1(); + var o1 = new object(); + var c1 = new C(); + var t1 = default(T); + var u1 = default(U); + void* p1 = null; + var a1 = new { X = 0 }; + var a2 = new int[1]; + var t2 = (0, 0); + } +}", options: TestOptions.Regular7_3); + var comp = CreateCompilationWithSpan(tree, TestOptions.UnsafeDebugDll); + Assert.True(comp.GetDiagnostics().All(d => d.Severity != DiagnosticSeverity.Error)); + var model = comp.GetSemanticModel(tree); + var root = tree.GetRoot(); + + Assert.True(getLocalType("span").IsRefLikeType); + Assert.False(getLocalType("s1").IsRefLikeType); + Assert.True(getLocalType("s2").IsRefLikeType); + Assert.False(getLocalType("i0").IsRefLikeType); + Assert.False(getLocalType("t1").IsRefLikeType); + Assert.False(getLocalType("e1").IsRefLikeType); + Assert.False(getLocalType("o1").IsRefLikeType); + Assert.False(getLocalType("c1").IsRefLikeType); + Assert.False(getLocalType("t1").IsRefLikeType); + Assert.False(getLocalType("u1").IsRefLikeType); + Assert.False(getLocalType("p1").IsRefLikeType); + Assert.False(getLocalType("a1").IsRefLikeType); + Assert.False(getLocalType("a2").IsRefLikeType); + Assert.False(getLocalType("t2").IsRefLikeType); + + ITypeSymbol getLocalType(string name) + { + var decl = root.DescendantNodes() + .OfType() + .Single(n => n.Identifier.ValueText == name); + return ((ILocalSymbol)model.GetDeclaredSymbol(decl)).Type; + } + } + [Fact] public void RefStructUsing() { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 074a5b1fe53..684cadc1a93 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -3012,6 +3012,71 @@ public void PointerToStructInPartialMethodSignature() CreateCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } + [Fact] + public void IsUnmanagedTypeSemanticModel() + { + var tree = SyntaxFactory.ParseSyntaxTree(@" +struct S1 { } +struct S2 { public S1 F1; } +struct S3 { public object F1; } +struct S4 { public T F1; } +struct S5 where T : unmanaged { public T F1; } +enum E1 { } +class C +{ + unsafe void M() where U : unmanaged + { + var s1 = new S1(); + var s2 = new S2(); + var s3 = new S3(); + var s4 = new S4(); + var s5 = new S4(); + var i0 = 0; + var e1 = new E1(); + var o1 = new object(); + var c1 = new C; + var t1 = default(T); + var u1 = default(U); + void* p1 = null; + var a1 = new { X = 0 }; + var a2 = new int[1]; + var t2 = (0, 0); + } +}"); + var comp = CreateCompilation(tree); + var model = comp.GetSemanticModel(tree); + var root = tree.GetRoot(); + // The spec states the following are unmanaged types: + // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool. + // Any enum_type. + // Any pointer_type. + // Any user-defined struct_type that is not a constructed type and contains fields of unmanaged_types only. + // A type parameter with an unmanaged constraint + Assert.True(getLocalType("s1").IsUnmanagedType); + Assert.True(getLocalType("s2").IsUnmanagedType); + Assert.False(getLocalType("s3").IsUnmanagedType); + Assert.False(getLocalType("s4").IsUnmanagedType); + Assert.False(getLocalType("s5").IsUnmanagedType); + Assert.True(getLocalType("i0").IsUnmanagedType); + Assert.True(getLocalType("e1").IsUnmanagedType); + Assert.False(getLocalType("o1").IsUnmanagedType); + Assert.False(getLocalType("c1").IsUnmanagedType); + Assert.False(getLocalType("t1").IsUnmanagedType); + Assert.True(getLocalType("u1").IsUnmanagedType); + Assert.True(getLocalType("p1").IsUnmanagedType); + Assert.False(getLocalType("a1").IsUnmanagedType); + Assert.False(getLocalType("a2").IsUnmanagedType); + Assert.False(getLocalType("t2").IsUnmanagedType); + + ITypeSymbol getLocalType(string name) + { + var decl = root.DescendantNodes() + .OfType() + .Single(n => n.Identifier.ValueText == name); + return ((ILocalSymbol)model.GetDeclaredSymbol(decl)).Type; + } + } + #endregion IsManagedType #region AddressOf operand kinds diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index 0d4147d4e04..9ea2ff7e0d0 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -5301,6 +5301,10 @@ public string ToMinimalDisplayString(SemanticModel semanticModel, int position, public bool IsSerializable => throw new NotImplementedException(); + public bool IsRefLikeType => throw new NotImplementedException(); + + public bool IsUnmanagedType => throw new NotImplementedException(); + #endregion } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index 0cb9f152f11..3cdb114a1fa 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs @@ -181,7 +181,7 @@ public override bool IsStatic } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ReadOnlyStructs.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ReadOnlyStructs.cs index 80bfc84e925..bf5691f0d16 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ReadOnlyStructs.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ReadOnlyStructs.cs @@ -39,19 +39,19 @@ class Program var s1 = comp.GetTypeByMetadataName("Program+S1"); - Assert.False(s1.IsByRefLikeType); + Assert.False(s1.IsRefLikeType); Assert.True(s1.IsReadOnly); Assert.Equal(Accessibility.Private, s1.DeclaredAccessibility); Assert.Equal(TypeKind.Struct, s1.TypeKind); var s2 = comp.GetTypeByMetadataName("Program+S2"); - Assert.False(s2.IsByRefLikeType); + Assert.False(s2.IsRefLikeType); Assert.True(s2.IsReadOnly); Assert.Equal(Accessibility.Public, s2.DeclaredAccessibility); Assert.Equal(TypeKind.Struct, s2.TypeKind); var s3 = comp.GetTypeByMetadataName("Program+S3"); - Assert.False(s3.IsByRefLikeType); + Assert.False(s3.IsRefLikeType); Assert.True(s3.IsReadOnly); Assert.Equal(Accessibility.Public, s3.DeclaredAccessibility); Assert.Equal(TypeKind.Struct, s3.TypeKind); @@ -113,19 +113,19 @@ class Program ); var s1 = comp.GetTypeByMetadataName("Program+S1"); - Assert.False(s1.IsByRefLikeType); + Assert.False(s1.IsRefLikeType); Assert.False(s1.IsReadOnly); Assert.Equal(Accessibility.Private, s1.DeclaredAccessibility); Assert.Equal(TypeKind.Class, s1.TypeKind); var s2 = comp.GetTypeByMetadataName("Program+S2"); - Assert.False(s2.IsByRefLikeType); + Assert.False(s2.IsRefLikeType); Assert.False(s2.IsReadOnly); Assert.Equal(Accessibility.Public, s2.DeclaredAccessibility); Assert.Equal(TypeKind.Delegate, s2.TypeKind); var s3 = comp.GetTypeByMetadataName("Program+S3"); - Assert.False(s3.IsByRefLikeType); + Assert.False(s3.IsRefLikeType); Assert.False(s3.IsReadOnly); Assert.Equal(Accessibility.Public, s3.DeclaredAccessibility); Assert.Equal(TypeKind.Interface, s3.TypeKind); @@ -148,13 +148,13 @@ class Program ); var s1 = comp.GetTypeByMetadataName("Program+S1"); - Assert.True(s1.IsByRefLikeType); + Assert.True(s1.IsRefLikeType); Assert.True(s1.IsReadOnly); Assert.Equal(Accessibility.Private, s1.DeclaredAccessibility); Assert.Equal(TypeKind.Struct, s1.TypeKind); var s2 = comp.GetTypeByMetadataName("Program+S2"); - Assert.True(s2.IsByRefLikeType); + Assert.True(s2.IsRefLikeType); Assert.True(s2.IsReadOnly); Assert.Equal(Accessibility.Public, s2.DeclaredAccessibility); Assert.Equal(TypeKind.Struct, s2.TypeKind); @@ -181,11 +181,11 @@ class Program ); var s1 = comp.GetTypeByMetadataName("Program+S1"); - Assert.False(s1.IsByRefLikeType); + Assert.False(s1.IsRefLikeType); Assert.True(s1.IsReadOnly); var s2 = comp.GetTypeByMetadataName("Program+S2"); - Assert.True(s2.IsByRefLikeType); + Assert.True(s2.IsRefLikeType); Assert.True(s2.IsReadOnly); } @@ -215,15 +215,15 @@ partial struct S3{} ); var s1 = comp.GetTypeByMetadataName("Program+S1"); - Assert.True(s1.IsByRefLikeType); + Assert.True(s1.IsRefLikeType); Assert.True(s1.IsReadOnly); var s2 = comp.GetTypeByMetadataName("Program+S2"); - Assert.False(s2.IsByRefLikeType); + Assert.False(s2.IsRefLikeType); Assert.True(s2.IsReadOnly); var s3 = comp.GetTypeByMetadataName("Program+S3"); - Assert.True(s3.IsByRefLikeType); + Assert.True(s3.IsRefLikeType); Assert.True(s3.IsReadOnly); } } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index a302f0f4ca1..c87b32c2a20 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -1,5 +1,7 @@ *REMOVED*Microsoft.CodeAnalysis.Operations.IEventAssignmentOperation.EventReference.get -> Microsoft.CodeAnalysis.Operations.IEventReferenceOperation Microsoft.CodeAnalysis.IFieldSymbol.IsFixedSizeBuffer.get -> bool +Microsoft.CodeAnalysis.ITypeSymbol.IsRefLikeType.get -> bool +Microsoft.CodeAnalysis.ITypeSymbol.IsUnmanagedType.get -> bool Microsoft.CodeAnalysis.OperationKind.Binary = 32 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConstructorBody = 89 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.DiscardPattern = 104 -> Microsoft.CodeAnalysis.OperationKind diff --git a/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs b/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs index 34be4b38590..3dcda1cc8da 100644 --- a/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs +++ b/src/Compilers/Core/Portable/Symbols/ITypeSymbol.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -95,6 +96,21 @@ public interface ITypeSymbol : INamespaceOrTypeSymbol /// Must be a non-null interface property, method, or event. /// ISymbol FindImplementationForInterfaceMember(ISymbol interfaceMember); + + /// + /// True if the type is ref-like, meaning it follows rules similar to CLR by-ref variables. False if the type + /// is not ref-like or if the language has no concept of ref-like types. + /// + /// + /// is a commonly used ref-like type. + /// + bool IsRefLikeType { get; } + + /// + /// True if the type is unmanaged according to language rules. False if managed or if the language + /// has no concept of unmanaged types. + /// + bool IsUnmanagedType { get; } } // Intentionally not extension methods. We don't want them ever be called for symbol classes diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index 2dc674cb156..9633cc9ca91 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -1746,6 +1746,22 @@ protected static void VerifyFlowGraph(CSharpCompilation compilation, SyntaxNode #region Span + protected static CSharpCompilation CreateCompilationWithSpan(SyntaxTree tree, CSharpCompilationOptions options = null) + { + var reference = CreateCompilation( + SpanSource, + options: TestOptions.UnsafeReleaseDll); + + reference.VerifyDiagnostics(); + + var comp = CreateCompilation( + tree, + references: new[] { reference.EmitToImageReference() }, + options: options); + + return comp; + } + protected static CSharpCompilation CreateCompilationWithMscorlibAndSpan(string text, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null) { var reference = CreateEmptyCompilation( diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb index 9188dc63512..2113d5a17bb 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeSymbol.vb @@ -510,6 +510,20 @@ Done: End Get End Property + Private ReadOnly Property ITypeSymbol_IsRefLikeType As Boolean Implements ITypeSymbol.IsRefLikeType + Get + ' VB has no concept of ref-like types + Return False + End Get + End Property + + Private ReadOnly Property ITypeSymbol_IsUnmanagedType As Boolean Implements ITypeSymbol.IsUnmanagedType + Get + ' VB has no concept of unmanaged types + Return False + End Get + End Property + #End Region #Region "Interface checks" diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb index 3ee8536c1da..d5d0ee72746 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelAPITests.vb @@ -1,5 +1,6 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic.Symbols @@ -2900,6 +2901,83 @@ End Class #Region "Msic." + + Public Sub IsUnmanagedType() + Dim csharpComp = CreateCSharpCompilation(" +public struct S1 { } +public struct S2 { public S1 F1; } +public struct S3 { public object F1; } +public struct S4 { public T F1; } +public enum E1 { } +") + Dim tree = SyntaxFactory.ParseSyntaxTree(" +Class C + Sub M() + Dim s1 = new S1() + Dim s2 = new S2() + Dim s3 = new S3() + Dim s4 = new S4(Of Integer)() + Dim e1 = new E1() + End Sub +End Class") + Dim comp = CreateCompilation(tree, references:={csharpComp.EmitToImageReference()}) + comp.AssertTheseCompileDiagnostics() + Dim model = comp.GetSemanticModel(tree) + Dim root = tree.GetRoot() + Dim getLocalType = Function(name As String) As ITypeSymbol + Dim decl = root.DescendantNodes(). + OfType(Of ModifiedIdentifierSyntax)(). + Single(Function(n) n.Identifier.ValueText = name) + Return CType(model.GetDeclaredSymbol(decl), ILocalSymbol).Type + End Function + ' VB does not have a concept of a managed type + Assert.False(getLocalType("s1").IsUnmanagedType) + Assert.False(getLocalType("s2").IsUnmanagedType) + Assert.False(getLocalType("s3").IsUnmanagedType) + Assert.False(getLocalType("s4").IsUnmanagedType) + Assert.False(getLocalType("e1").IsUnmanagedType) + End Sub + + + Public Sub IsRefLikeType() + Dim csharpComp = CreateCSharpCompilation(" +public struct S1 { } +public ref struct S2 { public S1 F1; } +public enum E1 { } +", parseOptions:=New CSharp.CSharpParseOptions(CSharp.LanguageVersion.CSharp7_3)) + Dim tree = SyntaxFactory.ParseSyntaxTree(" +Structure S3 + Dim F1 As Object +End Structure +Class C + Sub M() + Dim s1 = new S1() + Dim s2 = new S2() + Dim s3 = new S3() + Dim e1 = new E1() + End Sub +End Class") + Dim comp = CreateCompilation(tree, references:={csharpComp.EmitToImageReference()}) + comp.AssertTheseDiagnostics( +BC30668: 'S2' is obsolete: 'Types with embedded references are not supported in this version of your compiler.'. + Dim s2 = new S2() + ~~ + ) + Dim model = comp.GetSemanticModel(tree) + Dim root = tree.GetRoot() + Dim getLocalType = Function(name As String) As ITypeSymbol + Dim decl = root.DescendantNodes(). + OfType(Of ModifiedIdentifierSyntax)(). + Single(Function(n) n.Identifier.ValueText = name) + Return CType(model.GetDeclaredSymbol(decl), ILocalSymbol).Type + End Function + ' VB does not have a concept of a ref-like type + Assert.False(getLocalType("s1").IsRefLikeType) + Assert.False(getLocalType("s2").IsRefLikeType) + Assert.False(getLocalType("s3").IsRefLikeType) + Assert.False(getLocalType("e1").IsRefLikeType) + End Sub + Public Sub IsAccessible() Dim compilation = CompilationUtils.CreateCompilationWithMscorlib40( diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs index 3db7d6f3b18..e014cd88dcd 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs @@ -305,7 +305,7 @@ public override bool IsAbstract get { return false; } } - internal sealed override bool IsByRefLikeType + public sealed override bool IsRefLikeType { get { return false; } } diff --git a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs index 47cd6933c26..293e3ff84b0 100644 --- a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs +++ b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.WrappedNamedTypeSymbol.cs @@ -144,6 +144,10 @@ public override ImmutableArray GetTypeMembers(string name, int public new INamedTypeSymbol OriginalDefinition => this; public bool IsSerializable => throw new NotImplementedException(); + + public bool IsRefLikeType => throw new NotImplementedException(); + + public bool IsUnmanagedType => throw new NotImplementedException(); } } } diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationAbstractNamedTypeSymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationAbstractNamedTypeSymbol.cs index 4c01e094371..6007c1eaf5a 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationAbstractNamedTypeSymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationAbstractNamedTypeSymbol.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis.Editing; @@ -74,7 +75,7 @@ public ImmutableArray GetTypeArgumentCustomModifiers(int ordinal { if (ordinal < 0 || ordinal >= Arity) { - throw new System.IndexOutOfRangeException(); + throw new IndexOutOfRangeException(); } return ImmutableArray.Create(); @@ -97,5 +98,9 @@ public override string MetadataName public bool MightContainExtensionMethods => false; public bool IsComImport => false; + + public bool IsUnmanagedType => throw new NotImplementedException(); + + public bool IsRefLikeType => throw new NotImplementedException(); } } diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs index 6fd7d2744fe..047b78fc419 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeSymbol.cs @@ -54,5 +54,9 @@ public ImmutableArray AllInterfaces public override bool IsType => true; public bool IsSerializable => false; + + bool ITypeSymbol.IsRefLikeType => throw new System.NotImplementedException(); + + bool ITypeSymbol.IsUnmanagedType => throw new System.NotImplementedException(); } } -- GitLab