From 4b0e4284751f5d0d167fa901e2824c36bff74c20 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 8 Oct 2024 18:33:00 -0700 Subject: [PATCH 1/2] Do not use overload resolution while lowering interpolated strings Related to #74275. --- .../Portable/Binding/Binder_Conversions.vb | 4 +- .../Portable/Binding/Binder_Expressions.vb | 4 + .../Binding/Binder_InterpolatedString.vb | 171 +++++++++++++++++- .../Portable/Binding/Binder_XmlLiterals.vb | 2 +- .../Portable/BoundTree/BoundNodes.xml | 2 +- .../Generated/BoundNodes.xml.Generated.vb | 24 +-- .../DiagnosticsPass_ExpressionLambdas.vb | 4 + .../LocalRewriter_InterpolatedString.vb | 121 +------------ 8 files changed, 201 insertions(+), 131 deletions(-) diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb index 75d4e36989ad4..ea0d099de5abd 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb @@ -1618,7 +1618,9 @@ DoneWithDiagnostics: If (convKind And ConversionKind.InterpolatedString) = ConversionKind.InterpolatedString Then Debug.Assert(targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_IFormattable)) OrElse targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_FormattableString))) - Return New BoundConversion(tree, node, ConversionKind.InterpolatedString, False, isExplicit, targetType) + Return New BoundConversion(tree, + BindUnconvertedInterpolatedStringToFormattable(tree, node, targetType, diagnostics), + ConversionKind.InterpolatedString, False, isExplicit, targetType) End If Return node diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb index 3d93cd5b469d9..b95a41d77aa3c 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb @@ -1400,6 +1400,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Throw ExceptionUtilities.UnexpectedValue(propertyAccess.AccessKind) End Select + ElseIf expr.Kind = BoundKind.InterpolatedStringExpression Then + + expr = BindUnconvertedInterpolatedStringToString(DirectCast(expr, BoundInterpolatedStringExpression), diagnostics) + ElseIf expr.IsLateBound() Then Select Case expr.GetLateBoundAccessKind() diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb index d9cd0d0c3730d..7aab533abbe43 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb @@ -29,7 +29,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Select Next - Return New BoundInterpolatedStringExpression(syntax, contentBuilder.ToImmutableAndFree(), binder:=Me, type:=GetSpecialType(SpecialType.System_String, syntax, diagnostics)) + Return New BoundInterpolatedStringExpression(syntax, contentBuilder.ToImmutableAndFree(), constructionOpt:=Nothing, type:=GetSpecialType(SpecialType.System_String, syntax, diagnostics)) End Function @@ -72,5 +72,174 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Function + Private Function BindUnconvertedInterpolatedStringToString(node As BoundInterpolatedStringExpression, diagnostics As BindingDiagnosticBag) As BoundExpression + + Debug.Assert(node.Type.SpecialType = SpecialType.System_String) + + ' We lower an interpolated string into an invocation of String.Format or System.Runtime.CompilerServices.FormattableStringFactory.Create. + ' For example, we translate the expression: + ' + ' $"Jenny, don't change your number: {phoneNumber:###-####}." + ' + ' into + ' + ' String.Format("Jenny, don't change your number: {0:###-####}.", phoneNumber) + ' + ' TODO: A number of optimizations would be beneficial in the generated code. + ' + ' (1) If there is no width or format, and the argument is a value type, call .ToString() + ' on it directly so that we avoid the boxing overhead. + ' + ' (2) For the built-in types, we can use .ToString(string format) for some format strings. + ' Detect those cases that can be handled that way and take advantage of them. + If node.IsEmpty OrElse Not node.HasInterpolations Then + Return node + End If + + Return node.Update(node.Contents, + constructionOpt:=TryInvokeInterpolatedStringFactory(node, + factoryType:=node.Type, + factoryMethodName:="Format", + targetType:=node.Type, + diagnostics), + node.Type) + End Function + + Private Function BindUnconvertedInterpolatedStringToFormattable(syntax As SyntaxNode, node As BoundInterpolatedStringExpression, targetType As TypeSymbol, diagnostics As BindingDiagnosticBag) As BoundExpression + + Debug.Assert(targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_FormattableString)) OrElse + targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_IFormattable))) + + ' We lower an interpolated string into an invocation of System.Runtime.CompilerServices.FormattableStringFactory.Create. + ' For example, we translate the expression: + ' + ' $"Jenny, don't change your number: {phoneNumber:###-####}." + ' + ' into + ' + ' FormattableStringFactory.Create("Jenny, don't change your number: {0:###-####}.", phoneNumber) + ' + ' TODO: A number of optimizations would be beneficial in the generated code. + ' + ' (1) If there is no width or format, and the argument is a value type, call .ToString() + ' on it directly so that we avoid the boxing overhead. + ' + ' (2) For the built-in types, we can use .ToString(string format) for some format strings. + ' Detect those cases that can be handled that way and take advantage of them. + + Return node.Update(node.Contents, + constructionOpt:=TryInvokeInterpolatedStringFactory(node, + factoryType:=GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_FormattableStringFactory, syntax, diagnostics), + factoryMethodName:="Create", + targetType, + diagnostics), + node.Type) + End Function + + Private Function TryInvokeInterpolatedStringFactory(node As BoundInterpolatedStringExpression, factoryType As TypeSymbol, factoryMethodName As String, targetType As TypeSymbol, diagnostics As BindingDiagnosticBag) As BoundExpression + + Dim hasErrors As Boolean = False + + If factoryType.IsErrorType() OrElse + node.HasErrors OrElse + node.Contents.OfType(Of BoundInterpolation)().Any( + Function(interpolation) interpolation.Expression.HasErrors OrElse + (interpolation.AlignmentOpt IsNot Nothing AndAlso + Not (interpolation.AlignmentOpt.IsConstant AndAlso interpolation.AlignmentOpt.ConstantValueOpt.IsIntegral))) Then + Return Nothing + End If + + Dim lookup = LookupResult.GetInstance() + Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics) + + LookupMember(lookup, factoryType, factoryMethodName, 0, LookupOptions.MustNotBeInstance Or LookupOptions.MethodsOnly Or LookupOptions.AllMethodsOfAnyArity, useSiteInfo) + + diagnostics.Add(node, useSiteInfo) + + If lookup.Kind = LookupResultKind.Inaccessible Then + hasErrors = True + ElseIf Not lookup.IsGood Then + lookup.Free() + GoTo Report_ERR_InterpolatedStringFactoryError + End If + + Dim methodGroup = New BoundMethodGroup(node.Syntax, Nothing, lookup.Symbols.ToDowncastedImmutable(Of MethodSymbol), lookup.Kind, Nothing, QualificationKind.QualifiedViaTypeName).MakeCompilerGenerated() + lookup.Free() + + Dim formatStringBuilderHandle = PooledStringBuilder.GetInstance() + Dim arguments = ArrayBuilder(Of BoundExpression).GetInstance() + Dim interpolationOrdinal = -1 + + arguments.Add(Nothing) ' Placeholder for format string. + + For Each item In node.Contents + + Select Case item.Kind + + Case BoundKind.Literal + + formatStringBuilderHandle.Builder.Append(DirectCast(item, BoundLiteral).Value.StringValue) + + Case BoundKind.Interpolation + + interpolationOrdinal += 1 + + Dim interpolation = DirectCast(item, BoundInterpolation) + + With formatStringBuilderHandle.Builder + + .Append("{"c) + + .Append(interpolationOrdinal.ToString(Globalization.CultureInfo.InvariantCulture)) + + If interpolation.AlignmentOpt IsNot Nothing Then + Debug.Assert(interpolation.AlignmentOpt.IsConstant AndAlso interpolation.AlignmentOpt.ConstantValueOpt.IsIntegral) + .Append(","c) + .Append(interpolation.AlignmentOpt.ConstantValueOpt.Int64Value.ToString(Globalization.CultureInfo.InvariantCulture)) + End If + + If interpolation.FormatStringOpt IsNot Nothing Then + .Append(":") + .Append(interpolation.FormatStringOpt.Value.StringValue) + End If + + .Append("}"c) + End With + + arguments.Add(interpolation.Expression) + + Case Else + Throw ExceptionUtilities.Unreachable() + End Select + + Next + + arguments(0) = CreateStringLiteral(node.Syntax, formatStringBuilderHandle.ToStringAndFree(), compilerGenerated:=True, diagnostics) + + Dim result As BoundExpression = MakeRValue(BindInvocationExpression(node.Syntax, + node.Syntax, + TypeCharacter.None, + methodGroup, + arguments.ToImmutableAndFree(), + Nothing, + diagnostics, + callerInfoOpt:=Nothing, + forceExpandedForm:=True), diagnostics).MakeCompilerGenerated() + + If Not result.Type.Equals(targetType) Then + result = ApplyImplicitConversion(node.Syntax, targetType, result, diagnostics).MakeCompilerGenerated() + End If + + If hasErrors OrElse result.HasErrors Then + GoTo Report_ERR_InterpolatedStringFactoryError + End If + + Return result + +Report_ERR_InterpolatedStringFactoryError: + ReportDiagnostic(diagnostics, node.Syntax, ErrorFactory.ErrorInfo(ERRID.ERR_InterpolatedStringFactoryError, factoryType.Name, factoryMethodName)) + Return Nothing + End Function + End Class End Namespace diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb index d7bbfeb39bdfb..02b4d1fb55803 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb @@ -1048,7 +1048,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Function Private Function CreateStringLiteral( - syntax As VisualBasicSyntaxNode, + syntax As SyntaxNode, str As String, compilerGenerated As Boolean, diagnostics As BindingDiagnosticBag, diff --git a/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml b/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml index 20716accb919f..6087a847a95d2 100644 --- a/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml @@ -1927,7 +1927,7 @@ - + diff --git a/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb b/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb index 0a39a76c105d9..75908f54fc387 100644 --- a/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb +++ b/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb @@ -9239,15 +9239,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend NotInheritable Class BoundInterpolatedStringExpression Inherits BoundExpression - Public Sub New(syntax As SyntaxNode, contents As ImmutableArray(Of BoundNode), binder As Binder, type As TypeSymbol, Optional hasErrors As Boolean = False) - MyBase.New(BoundKind.InterpolatedStringExpression, syntax, type, hasErrors OrElse contents.NonNullAndHasErrors()) + Public Sub New(syntax As SyntaxNode, contents As ImmutableArray(Of BoundNode), constructionOpt As BoundExpression, type As TypeSymbol, Optional hasErrors As Boolean = False) + MyBase.New(BoundKind.InterpolatedStringExpression, syntax, type, hasErrors OrElse contents.NonNullAndHasErrors() OrElse constructionOpt.NonNullAndHasErrors()) Debug.Assert(Not (contents.IsDefault), "Field 'contents' cannot be null (use Null=""allow"" in BoundNodes.xml to remove this check)") - Debug.Assert(binder IsNot Nothing, "Field 'binder' cannot be null (use Null=""allow"" in BoundNodes.xml to remove this check)") Debug.Assert(type IsNot Nothing, "Field 'type' cannot be null (use Null=""allow"" in BoundNodes.xml to remove this check)") Me._Contents = contents - Me._Binder = binder + Me._ConstructionOpt = constructionOpt Validate() End Sub @@ -9263,10 +9262,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property - Private ReadOnly _Binder As Binder - Public ReadOnly Property Binder As Binder + Private ReadOnly _ConstructionOpt As BoundExpression + Public ReadOnly Property ConstructionOpt As BoundExpression Get - Return _Binder + Return _ConstructionOpt End Get End Property @@ -9275,9 +9274,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return visitor.VisitInterpolatedStringExpression(Me) End Function - Public Function Update(contents As ImmutableArray(Of BoundNode), binder As Binder, type As TypeSymbol) As BoundInterpolatedStringExpression - If contents <> Me.Contents OrElse binder IsNot Me.Binder OrElse type IsNot Me.Type Then - Dim result = New BoundInterpolatedStringExpression(Me.Syntax, contents, binder, type, Me.HasErrors) + Public Function Update(contents As ImmutableArray(Of BoundNode), constructionOpt As BoundExpression, type As TypeSymbol) As BoundInterpolatedStringExpression + If contents <> Me.Contents OrElse constructionOpt IsNot Me.ConstructionOpt OrElse type IsNot Me.Type Then + Dim result = New BoundInterpolatedStringExpression(Me.Syntax, contents, constructionOpt, type, Me.HasErrors) result.CopyAttributes(Me) Return result End If @@ -13126,8 +13125,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Overrides Function VisitInterpolatedStringExpression(node As BoundInterpolatedStringExpression) As BoundNode Dim contents As ImmutableArray(Of BoundNode) = Me.VisitList(node.Contents) + Dim constructionOpt As BoundExpression = node.ConstructionOpt Dim type as TypeSymbol = Me.VisitType(node.Type) - Return node.Update(contents, node.Binder, type) + Return node.Update(contents, constructionOpt, type) End Function Public Overrides Function VisitInterpolation(node As BoundInterpolation) As BoundNode @@ -14589,7 +14589,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Overrides Function VisitInterpolatedStringExpression(node As BoundInterpolatedStringExpression, arg As Object) As TreeDumperNode Return New TreeDumperNode("interpolatedStringExpression", Nothing, New TreeDumperNode() { New TreeDumperNode("contents", Nothing, From x In node.Contents Select Visit(x, Nothing)), - New TreeDumperNode("binder", node.Binder, Nothing), + New TreeDumperNode("constructionOpt", Nothing, new TreeDumperNode() {Visit(node.ConstructionOpt, Nothing)}), New TreeDumperNode("type", node.Type, Nothing) }) End Function diff --git a/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb b/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb index cc44e74774a88..786b7d35f6080 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb @@ -405,6 +405,10 @@ lSelect: Me._diagnostics.Add(New VBDiagnostic(ErrorFactory.ErrorInfo(code), node.Syntax.GetLocation())) End Sub + Public Overrides Function VisitInterpolatedStringExpression(node As BoundInterpolatedStringExpression) As BoundNode + Visit(node.ConstructionOpt) + Return MyBase.VisitInterpolatedStringExpression(node) + End Function End Class End Namespace diff --git a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb index 8002dbc4b5c63..3570e6a0a55c2 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb @@ -46,7 +46,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return factory.StringLiteral(ConstantValue.Create(valueWithEscapes.Replace("{{", "{").Replace("}}", "}"))) Else - Return InvokeInterpolatedStringFactory(node, node.Type, "Format", node.Type, factory) + Debug.Assert(node.ConstructionOpt IsNot Nothing) + Return VisitExpression(node.ConstructionOpt) End If End Function @@ -57,10 +58,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim targetType = conversion.Type Dim node = DirectCast(conversion.Operand, BoundInterpolatedStringExpression) - Dim binder = node.Binder + Debug.Assert(node.ConstructionOpt IsNot Nothing) - Debug.Assert(targetType.Equals(binder.Compilation.GetWellKnownType(WellKnownType.System_FormattableString)) OrElse - targetType.Equals(binder.Compilation.GetWellKnownType(WellKnownType.System_IFormattable))) + Debug.Assert(targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_FormattableString)) OrElse + targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_IFormattable))) ' We lower an interpolated string into an invocation of System.Runtime.CompilerServices.FormattableStringFactory.Create. ' For example, we translate the expression: @@ -78,117 +79,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' ' (2) For the built-in types, we can use .ToString(string format) for some format strings. ' Detect those cases that can be handled that way and take advantage of them. - Return InvokeInterpolatedStringFactory(node, - binder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_FormattableStringFactory, conversion.Syntax, _diagnostics), - "Create", - conversion.Type, - New SyntheticBoundNodeFactory(_topMethod, _currentMethodOrLambda, node.Syntax, _compilationState, _diagnostics)) - - End Function - - Private Function InvokeInterpolatedStringFactory(node As BoundInterpolatedStringExpression, factoryType As TypeSymbol, factoryMethodName As String, targetType As TypeSymbol, factory As SyntheticBoundNodeFactory) As BoundExpression - - Dim hasErrors As Boolean = False - - If factoryType.IsErrorType() Then - GoTo ReturnBadExpression - End If - - Dim binder = node.Binder - - Dim lookup = LookupResult.GetInstance() - Dim useSiteInfo = GetNewCompoundUseSiteInfo() - - binder.LookupMember(lookup, factoryType, factoryMethodName, 0, LookupOptions.MustNotBeInstance Or LookupOptions.MethodsOnly Or LookupOptions.AllMethodsOfAnyArity, useSiteInfo) - - _diagnostics.Add(node, useSiteInfo) - - If lookup.Kind = LookupResultKind.Inaccessible Then - hasErrors = True - ElseIf Not lookup.IsGood Then - lookup.Free() - GoTo ReturnBadExpression - End If - - Dim methodGroup = New BoundMethodGroup(node.Syntax, Nothing, lookup.Symbols.ToDowncastedImmutable(Of MethodSymbol), lookup.Kind, Nothing, QualificationKind.QualifiedViaTypeName).MakeCompilerGenerated() - lookup.Free() - - Dim formatStringBuilderHandle = PooledStringBuilder.GetInstance() - Dim arguments = ArrayBuilder(Of BoundExpression).GetInstance() - Dim interpolationOrdinal = -1 - - arguments.Add(Nothing) ' Placeholder for format string. - - For Each item In node.Contents - - Select Case item.Kind - - Case BoundKind.Literal - - formatStringBuilderHandle.Builder.Append(DirectCast(item, BoundLiteral).Value.StringValue) - - Case BoundKind.Interpolation - - interpolationOrdinal += 1 - - Dim interpolation = DirectCast(item, BoundInterpolation) - - With formatStringBuilderHandle.Builder - - .Append("{"c) - - .Append(interpolationOrdinal.ToString(Globalization.CultureInfo.InvariantCulture)) - - If interpolation.AlignmentOpt IsNot Nothing Then - Debug.Assert(interpolation.AlignmentOpt.IsConstant AndAlso interpolation.AlignmentOpt.ConstantValueOpt.IsIntegral) - .Append(","c) - .Append(interpolation.AlignmentOpt.ConstantValueOpt.Int64Value.ToString(Globalization.CultureInfo.InvariantCulture)) - End If - - If interpolation.FormatStringOpt IsNot Nothing Then - .Append(":") - .Append(interpolation.FormatStringOpt.Value.StringValue) - End If - - .Append("}"c) - End With - - arguments.Add(interpolation.Expression) - - Case Else - Throw ExceptionUtilities.Unreachable() - End Select - - Next - - arguments(0) = factory.StringLiteral(ConstantValue.Create(formatStringBuilderHandle.ToStringAndFree())).MakeCompilerGenerated() - - Dim result As BoundExpression = binder.MakeRValue(binder.BindInvocationExpression(node.Syntax, - node.Syntax, - TypeCharacter.None, - methodGroup, - arguments.ToImmutableAndFree(), - Nothing, - _diagnostics, - callerInfoOpt:=Nothing, - forceExpandedForm:=True), _diagnostics).MakeCompilerGenerated() - - If Not result.Type.Equals(targetType) Then - result = binder.ApplyImplicitConversion(node.Syntax, targetType, result, _diagnostics).MakeCompilerGenerated() - End If - - If hasErrors OrElse result.HasErrors Then - GoTo ReturnBadExpression - End If - - result = VisitExpression(result) - - Return result - -ReturnBadExpression: - ReportDiagnostic(node, ErrorFactory.ErrorInfo(ERRID.ERR_InterpolatedStringFactoryError, factoryType.Name, factoryMethodName), _diagnostics) - Return factory.Convert(targetType, factory.BadExpression(DirectCast(MyBase.VisitInterpolatedStringExpression(node), BoundExpression))) - + Return VisitExpression(node.ConstructionOpt) End Function End Class From 557190ef59ce4867de55ab085e3bb87abbfebc7f Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 9 Oct 2024 10:51:10 -0700 Subject: [PATCH 2/2] Fixup --- .../LocalRewriter/LocalRewriter_Conversion.vb | 86 ------------------- 1 file changed, 86 deletions(-) diff --git a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb index e727785341c65..7b7cae1b91a71 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb @@ -591,92 +591,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return operand End Function - Private Function RewriteNullableReferenceConversion(node As BoundConversion, - rewrittenOperand As BoundExpression) As BoundExpression - - Dim resultType = node.Type - Dim operandType = rewrittenOperand.Type - - If operandType.IsStringType Then - ' CType(string, T?) ---> new T?(CType(string, T)) - Dim innerTargetType = resultType.GetNullableUnderlyingType - Dim useSiteInfo = GetNewCompoundUseSiteInfo() - Dim convKind = Conversions.ClassifyConversion(operandType, innerTargetType, useSiteInfo).Key - Debug.Assert(Conversions.ConversionExists(convKind)) - _diagnostics.Add(node, useSiteInfo) - Return WrapInNullable( - TransformRewrittenConversion( - node.Update(rewrittenOperand, - convKind, - node.Checked, - node.ExplicitCastInCode, - node.ConstantValueOpt, - node.ExtendedInfoOpt, - resultType.GetNullableUnderlyingType)), - resultType) - End If - - If resultType.IsStringType Then - ' conversion to string is an intrinsic conversion and can be lifted. - ' T? --> string ==> T.Value -- string - ' note that nullable null does not convert to string null, i.e. this conversion - ' is not null-propagating - - rewrittenOperand = NullableValue(rewrittenOperand) - Dim useSiteInfo = GetNewCompoundUseSiteInfo() - Dim convKind = Conversions.ClassifyDirectCastConversion(rewrittenOperand.Type, resultType, useSiteInfo) - Debug.Assert(Conversions.ConversionExists(convKind)) - _diagnostics.Add(node, useSiteInfo) - Return TransformRewrittenConversion( - node.Update(rewrittenOperand, - node.ConversionKind And (Not ConversionKind.Nullable), - node.Checked, - node.ExplicitCastInCode, - node.ConstantValueOpt, - node.ExtendedInfoOpt, - resultType)) - End If - - If operandType.IsNullableType Then - ' T? --> RefType, this is a boxing conversion (DirectCast) - If HasNoValue(rewrittenOperand) Then - ' DirectCast(Nothing, operatorType) - Return New BoundDirectCast(node.Syntax, - MakeNullLiteral(rewrittenOperand.Syntax, resultType), - ConversionKind.WideningNothingLiteral, - resultType) - End If - - If HasValue(rewrittenOperand) Then - ' DirectCast(operand.GetValueOrDefault, operatorType) - Dim unwrappedOperand = NullableValueOrDefault(rewrittenOperand) - Dim useSiteInfo = GetNewCompoundUseSiteInfo() - Dim convKind = Conversions.ClassifyDirectCastConversion(unwrappedOperand.Type, resultType, useSiteInfo) - Debug.Assert(Conversions.ConversionExists(convKind)) - _diagnostics.Add(node, useSiteInfo) - Return New BoundDirectCast(node.Syntax, - unwrappedOperand, - convKind, - resultType) - End If - End If - - If resultType.IsNullableType Then - ' RefType --> T? , this is just an unboxing conversion. - Dim useSiteInfo = GetNewCompoundUseSiteInfo() - Dim convKind = Conversions.ClassifyDirectCastConversion(rewrittenOperand.Type, resultType, useSiteInfo) - Debug.Assert(Conversions.ConversionExists(convKind)) - _diagnostics.Add(node, useSiteInfo) - Return New BoundDirectCast(node.Syntax, - rewrittenOperand, - convKind, - resultType) - - End If - - Throw ExceptionUtilities.Unreachable - End Function - Private Function RewriteNullableUserDefinedConversion(node As BoundUserDefinedConversion) As BoundNode ' User defined conversions rewrite as: ' Sequence(operandCapture, If(operandCapture.HasValue, Conversion(operandCapture), Null)