Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP][Personal] TypeOf over multiple types. #21034

Closed
wants to merge 11 commits into from
2 changes: 2 additions & 0 deletions src/Compilers/Core/Portable/CodeAnalysis.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
<Compile Include="Operations\IObjectCreationExpression.cs" />
<Compile Include="Operations\IOmittedArgumentExpression.cs" />
<Compile Include="Operations\IOperationWithChildren.cs" />
<Compile Include="Operations\ITypeArray.cs" />
<Compile Include="Operations\ObjectCreationExpression_IHasArgumentsExpression.cs" />
<Compile Include="Operations\Operation.cs" />
<Compile Include="Operations\IOperationKind.cs" />
Expand Down Expand Up @@ -146,6 +147,7 @@
<Compile Include="Serialization\ObjectBinderSnapshot.cs" />
<Compile Include="Serialization\ObjectReader.cs" />
<Compile Include="Serialization\ObjectWriter.cs" />
<Compile Include="Symbols\ITypeArraySymbol.cs" />
<Compile Include="Symbols\IDiscardSymbol.cs" />
<Compile Include="Syntax\InternalSyntax\GreenNodeExtensions.cs" />
<Compile Include="Syntax\InternalSyntax\SyntaxListPool.cs" />
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/Core/Portable/Operations/IOperationKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,5 +185,7 @@ public enum OperationKind
RelationalCaseClause = 0x40b,
/// <summary>Indicates an <see cref="IRangeCaseClause"/>.</summary>
RangeCaseClause = 0x40c,
/// <summary>Indicates an <see cref="ITypeArray"/>.</summary>
TypeArray = 0x40d,
}
}
18 changes: 18 additions & 0 deletions src/Compilers/Core/Portable/Operations/ITypeArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// 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.Collections.Immutable;

namespace Microsoft.CodeAnalysis.Semantics
{
/// <summary>
/// Represents a TypeOf expression.
/// </summary>
/// <remarks>
/// This interface is reserved for implementation by its associated APIs. We reserve the right to
/// change it in the future.
/// </remarks>
public interface ITypeArray : IOperation
{
}
}

7 changes: 7 additions & 0 deletions src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Microsoft.CodeAnalysis.IOperation.IsInvalid.get -> bool
Microsoft.CodeAnalysis.IOperation.Kind.get -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.IOperation.Syntax.get -> Microsoft.CodeAnalysis.SyntaxNode
Microsoft.CodeAnalysis.IOperation.Type.get -> Microsoft.CodeAnalysis.ITypeSymbol
Microsoft.CodeAnalysis.ITypeArraySymbol
Microsoft.CodeAnalysis.ITypeArraySymbol.Equals(Microsoft.CodeAnalysis.IArrayTypeSymbol other) -> bool
Microsoft.CodeAnalysis.ITypeArraySymbol.Types() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol>
Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.AddressOfExpression = 515 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.Argument = 1031 -> Microsoft.CodeAnalysis.OperationKind
Expand Down Expand Up @@ -116,6 +119,7 @@ Microsoft.CodeAnalysis.OperationKind.SwitchStatement = 4 -> Microsoft.CodeAnalys
Microsoft.CodeAnalysis.OperationKind.SyntheticLocalReferenceExpression = 263 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.ThrowStatement = 10 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.TryStatement = 14 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.TypeArray = 1037 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.TypeOfExpression = 513 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.TypeParameterObjectCreationExpression = 275 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.UnaryOperatorExpression = 269 -> Microsoft.CodeAnalysis.OperationKind
Expand Down Expand Up @@ -503,6 +507,7 @@ Microsoft.CodeAnalysis.Semantics.ITryStatement
Microsoft.CodeAnalysis.Semantics.ITryStatement.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement
Microsoft.CodeAnalysis.Semantics.ITryStatement.Catches.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Semantics.ICatchClause>
Microsoft.CodeAnalysis.Semantics.ITryStatement.FinallyHandler.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement
Microsoft.CodeAnalysis.Semantics.ITypeArray
Microsoft.CodeAnalysis.Semantics.ITypeOfExpression
Microsoft.CodeAnalysis.Semantics.ITypeOperationExpression
Microsoft.CodeAnalysis.Semantics.ITypeOperationExpression.TypeOperand.get -> Microsoft.CodeAnalysis.ITypeSymbol
Expand Down Expand Up @@ -915,3 +920,5 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.Vi
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitWhileUntilLoopStatement(Microsoft.CodeAnalysis.Semantics.IWhileUntilLoopStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitWithStatement(Microsoft.CodeAnalysis.Semantics.IWithStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitYieldBreakStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.SymbolVisitor.VisitTypeArray(Microsoft.CodeAnalysis.ITypeArraySymbol symbol) -> void
virtual Microsoft.CodeAnalysis.SymbolVisitor<TResult>.VisitTypeArray(Microsoft.CodeAnalysis.ITypeArraySymbol symbol) -> TResult
26 changes: 26 additions & 0 deletions src/Compilers/Core/Portable/Symbols/ITypeArraySymbol.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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.Collections.Immutable;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis
{
/// <summary>
/// Represents an array.
/// </summary>
/// <remarks>
/// This interface is reserved for implementation by its associated APIs. We reserve the right to
/// change it in the future.
/// </remarks>
public interface ITypeArraySymbol : ITypeSymbol
{
ImmutableArray<ITypeSymbol> Types();

///// <summary>
///// Custom modifiers associated with the array type, or an empty array if there are none.
///// </summary>
//ImmutableArray<CustomModifier> CustomModifiers { get; }

bool Equals(IArrayTypeSymbol other);
}
}
4 changes: 4 additions & 0 deletions src/Compilers/Core/Portable/Symbols/SymbolVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public virtual void VisitArrayType(IArrayTypeSymbol symbol)
DefaultVisit(symbol);
}

public virtual void VisitTypeArray(ITypeArraySymbol symbol)
{
DefaultVisit(symbol);
}
public virtual void VisitAssembly(IAssemblySymbol symbol)
{
DefaultVisit(symbol);
Expand Down
4 changes: 4 additions & 0 deletions src/Compilers/Core/Portable/Symbols/SymbolVisitor`1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public virtual TResult VisitArrayType(IArrayTypeSymbol symbol)
{
return DefaultVisit(symbol);
}
public virtual TResult VisitTypeArray(ITypeArraySymbol symbol)
{
return DefaultVisit(symbol);
}

public virtual TResult VisitAssembly(IAssemblySymbol symbol)
{
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/VisualBasic/Portable/BasicCodeAnalysis.vbproj
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
<Compile Include="BoundTree\BoundTreeVisitor.vb" />
<Compile Include="BoundTree\BoundTreeWalker.vb" />
<Compile Include="BoundTree\BoundTryCast.vb" />
<Compile Include="BoundTree\BoundTypeArray.vb" />
<Compile Include="BoundTree\BoundTypeExpression.vb" />
<Compile Include="BoundTree\BoundTypeOrValueExpression.vb" />
<Compile Include="BoundTree\BoundUnaryOperator.vb" />
Expand Down Expand Up @@ -768,6 +769,7 @@
<Compile Include="Symbols\Source\SynthesizedStaticLocalBackingField.vb" />
<Compile Include="Symbols\Source\SynthesizedSubmissionConstructorSymbol.vb" />
<Compile Include="Symbols\Source\SynthesizedWithEventsAccessorSymbol.vb" />
<Compile Include="Symbols\Source\TypeArraySymbol.vb" />
<Compile Include="Symbols\Source\TypeParameterConstraintKind.vb" />
<Compile Include="Symbols\Source\UnboundLambdaParameterSymbol.vb" />
<Compile Include="Symbols\SpecialMembers.vb" />
Expand Down
114 changes: 102 additions & 12 deletions src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Case SyntaxKind.InterpolatedStringExpression
Return BindInterpolatedStringExpression(DirectCast(node, InterpolatedStringExpressionSyntax), diagnostics)

Case SyntaxKind.TypeArray
Return BindTypeArray(DirectCast(node, TypeArraySyntax), diagnostics)

Case SyntaxKind.TupleExpression
Return BindTupleExpression(DirectCast(node, TupleExpressionSyntax), diagnostics)

Expand Down Expand Up @@ -585,7 +588,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function

Public Function BindNamespaceOrTypeOrExpressionSyntaxForSemanticModel(node As ExpressionSyntax, diagnostics As DiagnosticBag) As BoundExpression
If (node.Kind = SyntaxKind.PredefinedType) OrElse
If (node.Kind = SyntaxKind.PredefinedType) OrElse (node.Kind = SyntaxKind.TypeArray) OrElse
(((TypeOf node Is NameSyntax) OrElse node.Kind = SyntaxKind.ArrayType OrElse node.Kind = SyntaxKind.TupleType) AndAlso SyntaxFacts.IsInNamespaceOrTypeContext(node)) Then
Dim result As BoundExpression = Me.BindNamespaceOrTypeExpression(DirectCast(node, TypeSyntax), diagnostics)

Expand Down Expand Up @@ -738,25 +741,91 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
End Sub

Private Function BindTypeOfExpression(node As TypeOfExpressionSyntax, diagnostics As DiagnosticBag) As BoundExpression
Private Function BindTypeArray(node As TypeArraySyntax, diagnostics As DiagnosticBag) As BoundExpression
Dim _Targets_ As New List(Of TypeSymbol)(node._Types_.Count)
For i = 0 To node._Types_.Count - 1
Dim target = node._Types_(i)
Dim targetSymbol As Symbol = BindTypeOrAliasSyntax(target, diagnostics)
Dim targetType = DirectCast(If(TryCast(targetSymbol, TypeSymbol), DirectCast(targetSymbol, AliasSymbol).Target), TypeSymbol)
_Targets_.Add(targetType)
Next
Dim results = _Targets_.ToImmutableArrayOrEmpty
Return New BoundTypeArray(node, results, New TypeArraySymbol(results))
End Function

Dim operand = BindRValue(node.Expression, diagnostics, isOperandOfConditionalBranch:=False)
Dim operandType = operand.Type

Dim operatorIsIsNot = (node.Kind = SyntaxKind.TypeOfIsNotExpression)
Private Function BindTypeArray(node As TypeArraySyntax, diagnostics As DiagnosticBag, operandType As TypeSymbol) As BoundExpression
Dim _Targets_ As New List(Of TypeSymbol)(node._Types_.Count)
For i = 0 To node._Types_.Count - 1
Dim target = node._Types_(i)
Dim targetSymbol As Symbol = BindTypeOrAliasSyntax(target, diagnostics)
Dim targetType = DirectCast(If(TryCast(targetSymbol, TypeSymbol), DirectCast(targetSymbol, AliasSymbol).Target), TypeSymbol)

If targetType.IsErrorType() Then
' If target types have errors, bail out preventing more cascading errors.
'Return New BoundTypeOf(node, operand, operatorIsIsNot, targetType, resultType)
Else

If Not operandType.IsReferenceType AndAlso Not operandType.IsTypeParameter() Then

ReportDiagnostic(diagnostics, target, ERRID.ERR_TypeOfRequiresReferenceType1, operandType)

Else
Dim useSiteDiagnostics As HashSet(Of DiagnosticInfo) = Nothing
Dim convKind As ConversionKind = Conversions.ClassifyTryCastConversion(operandType, targetType, useSiteDiagnostics)

If diagnostics.Add(target, useSiteDiagnostics) Then
' Suppress any additional diagnostics
diagnostics = New DiagnosticBag()
ElseIf Not Conversions.ConversionExists(convKind) Then
ReportDiagnostic(diagnostics, target, ERRID.ERR_TypeOfExprAlwaysFalse2, operandType, targetType)
End If
End If

''If operandType.IsTypeParameter() Then
'' operand = ApplyImplicitConversion(node, GetSpecialType(SpecialType.System_Object, node.Expression, diagnostics), operand, diagnostics)
''End If
End If
_Targets_.Add(targetType)
Next
Dim results = _Targets_.ToImmutableArrayOrEmpty
Return New BoundTypeArray(node, results, New TypeArraySymbol(results))
End Function

Private Function BindTypeOfManyExpression(node As TypeOfExpressionSyntax,
diagnostics As DiagnosticBag,
operand As BoundExpression,
operandType As TypeSymbol,
operatorIsIsNot As Boolean,
ResultType As TypeSymbol) As BoundExpression
'
' TypeOf expr Is { T0, ... }
' TypeOf expr IsNot { T0, ... }
'
Dim _Ta_ = BindTypeArray(DirectCast(node.Type, TypeArraySyntax), diagnostics, operandType)
Return New BoundTypeOf(node, operand, operatorIsIsNot, _Ta_.Type, ResultType)
End Function

Private Function BindTypeOfOneExpression(node As TypeOfExpressionSyntax,
diagnostics As DiagnosticBag,
operand As BoundExpression,
operandType As TypeSymbol,
operatorIsIsNot As Boolean,
ResultType As TypeSymbol) As BoundExpression
'
' TypeOf expr Is T0
' TypeOf expr IsNot T0
'
Dim targetSymbol As Symbol = BindTypeOrAliasSyntax(node.Type, diagnostics)
Dim targetType = DirectCast(If(TryCast(targetSymbol, TypeSymbol), DirectCast(targetSymbol, AliasSymbol).Target), TypeSymbol)

Dim resultType As TypeSymbol = GetSpecialType(SpecialType.System_Boolean, node, diagnostics)

If operand.HasErrors OrElse operandType.IsErrorType() OrElse targetType.IsErrorType() Then
' If operand is bad or either the source or target types have errors, bail out preventing more cascading errors.
Return New BoundTypeOf(node, operand, operatorIsIsNot, targetType, resultType)
If targetType.IsErrorType() Then
' If target types have errors, bail out preventing more cascading errors.
Return New BoundTypeOf(node, operand, operatorIsIsNot, targetType, ResultType)
End If

If Not operandType.IsReferenceType AndAlso
Not operandType.IsTypeParameter() Then
If Not operandType.IsReferenceType AndAlso Not operandType.IsTypeParameter() Then

ReportDiagnostic(diagnostics, node.Expression, ERRID.ERR_TypeOfRequiresReferenceType1, operandType)

Expand All @@ -776,7 +845,28 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
operand = ApplyImplicitConversion(node, GetSpecialType(SpecialType.System_Object, node.Expression, diagnostics), operand, diagnostics)
End If

Return New BoundTypeOf(node, operand, operatorIsIsNot, targetType, resultType)
Return New BoundTypeOf(node, operand, operatorIsIsNot, targetType, ResultType)

End Function

Private Function BindTypeOfExpression(node As TypeOfExpressionSyntax, diagnostics As DiagnosticBag) As BoundExpression

Dim operand = BindRValue(node.Expression, diagnostics, isOperandOfConditionalBranch:=False)
Dim operandType = operand.Type

Dim operatorIsIsNot = (node.Kind = SyntaxKind.TypeOfIsNotExpression)
Dim resultType As TypeSymbol = GetSpecialType(SpecialType.System_Boolean, node, diagnostics)
If operand.HasErrors OrElse operandType.IsErrorType() Then
' If operand is bad or either the source, bail out preventing more cascading errors.
Return New BoundTypeOf(node, operand, operatorIsIsNot, Nothing, resultType)
End If
' Dealing with { ... } ?

If TypeOf node.Type Is TypeArraySyntax Then
Return BindTypeOfManyExpression(node, diagnostics, operand, operandType, operatorIsIsNot, resultType)
Else
Return BindTypeOfOneExpression(node, diagnostics, operand, operandType, operatorIsIsNot, resultType)
End If

End Function

Expand Down
Loading