Skip to content

Commit

Permalink
Fix InvalidCastException when initializing the properties of an undec…
Browse files Browse the repository at this point in the history
…lared class inside a lambda function (#72480)

Fixes #72456.

Building the following snippet in a VB project breaks the compilation:
```vb
Imports System
Imports System.Linq.Expressions
Module Program
    Public Function CreateExpression() As Expression(Of Func(Of Object))
        Return Function() (New UndeclaredClass() With {.Name = "testName"})
    End Function
End Module
```

There is a difference between `VisualBasic` and `CSharp` when getting diagnostics for the snippet above. The latter checks for the initializer type while the former forces a `DirectCast` which throws an `InvalidCastException`. This PR checks the type before forcing the cast similar to the `CSharp` approach.

### Expected result
`Error BC30002: Type 'UndeclaredClass' is not defined.`
### Actual result
Compilation breaks with the following trace:
```
System.InvalidCastException
  HResult=0x80004002
  Message=Unable to cast object of type 'Microsoft.CodeAnalysis.VisualBasic.BoundLiteral' to type 'Microsoft.CodeAnalysis.VisualBasic.BoundAssignmentOperator'.

This exception was originally thrown at this call stack:
Microsoft.CodeAnalysis.VisualBasic.dll!Microsoft.CodeAnalysis.VisualBasic.DiagnosticsPass.VisitObjectInitializerExpression(Microsoft.CodeAnalysis.VisualBasic.BoundObjectInitializerExpression node) Line 126	Basic
Microsoft.CodeAnalysis.VisualBasic.dll!Microsoft.CodeAnalysis.VisualBasic.BoundObjectInitializerExpression.Accept(Microsoft.CodeAnalysis.VisualBasic.BoundTreeVisitor visitor) Line 3792	Basic
Microsoft.CodeAnalysis.VisualBasic.dll!Microsoft.CodeAnalysis.VisualBasic.BoundTreeWalkerWithStackGuard.VisitExpressionWithoutStackGuard(Microsoft.CodeAnalysis.VisualBasic.BoundExpression node) Line 61	Basic
Microsoft.CodeAnalysis.VisualBasic.dll!Microsoft.CodeAnalysis.VisualBasic.BoundTreeVisitor.VisitExpressionWithStackGuard(Integer recursionDepth, Microsoft.CodeAnalysis.VisualBasic.BoundExpression node) Line 186	Basic
Microsoft.CodeAnalysis.VisualBasic.dll!Microsoft.CodeAnalysis.VisualBasic.BoundTreeWalkerWithStackGuard.Visit(Microsoft.CodeAnalysis.VisualBasic.BoundNode node) Line 50	Basic
Microsoft.CodeAnalysis.VisualBasic.dll!Microsoft.CodeAnalysis.VisualBasic.DiagnosticsPass.Visit(Microsoft.CodeAnalysis.VisualBasic.BoundNode node) Line 208	Basic
...
```
  • Loading branch information
andrei-ungureanu-uipath authored Mar 14, 2024
1 parent 26b809d commit 224f1a3
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic

For Each initializer In node.Initializers
' Ignore assignments in object initializers, only reference the value
Debug.Assert(initializer.Kind = BoundKind.AssignmentOperator)
Dim assignment = DirectCast(initializer, BoundAssignmentOperator)
Debug.Assert(assignment.LeftOnTheRightOpt Is Nothing)

Dim propertyAccess = TryCast(assignment.Left, BoundPropertyAccess)
If propertyAccess IsNot Nothing Then
CheckRefReturningPropertyAccess(propertyAccess)
Dim boundExpression As BoundExpression = initializer
If boundExpression.Kind = BoundKind.AssignmentOperator Then
Dim assignment = DirectCast(initializer, BoundAssignmentOperator)
Debug.Assert(assignment.LeftOnTheRightOpt Is Nothing)

boundExpression = assignment.Right
Dim propertyAccess = TryCast(assignment.Left, BoundPropertyAccess)
If propertyAccess IsNot Nothing Then
CheckRefReturningPropertyAccess(propertyAccess)
End If
End If

Me.Visit(assignment.Right)
Me.Visit(boundExpression)
Next

Me._expressionTreePlaceholders.Remove(placeholder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2015,6 +2015,31 @@ End Module
CompileAndVerify(source, references:={Net40.SystemCore}).VerifyDiagnostics()
End Sub

<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72456")>
Public Sub UndeclaredClassInLambdaFunction()
Dim source =
<compilation>
<file name="expr.vb"><![CDATA[
Imports System
Imports System.Linq.Expressions
Module Program
Public Function CreateExpression() As Expression(Of Func(Of Object))
Return Function() (New UndeclaredClass() With {.Name = "testName"})
End Function
End Module
]]>
</file>
</compilation>

Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(source, {LinqAssemblyRef})
AssertTheseDiagnostics(compilation.GetDiagnostics(),
<expected>
BC30002: Type 'UndeclaredClass' is not defined.
Return Function() (New UndeclaredClass() With {.Name = "testName"})
~~~~~~~~~~~~~~~
</expected>)
End Sub

<Fact>
<WorkItem(577271, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/577271")>
Public Sub Bug577271()
Expand Down

0 comments on commit 224f1a3

Please sign in to comment.