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

Use non-void type for BoundAwaitOperator in VB statement #67822

Merged
merged 6 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -510,5 +510,35 @@ static async Task M(bool b, int i)
";
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}

[CompilerTrait(CompilerFeature.IOperation)]
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67616")]
public void TestAwaitExpression_InStatement()
{
string source = @"
using System.Threading.Tasks;

class C
{
static async Task M()
{
/*<bind>*/await M2()/*</bind>*/;
}

static Task<string> M2() => throw null;
}
";
string expectedOperationTree = @"
IAwaitOperation (OperationKind.Await, Type: System.String) (Syntax: 'await M2()')
Expression:
IInvocationOperation (System.Threading.Tasks.Task<System.String> C.M2()) (OperationKind.Invocation, Type: System.Threading.Tasks.Task<System.String>) (Syntax: 'M2()')
Instance Receiver:
null
Arguments(0)
";
var expectedDiagnostics = DiagnosticDescription.None;

VerifyOperationTreeAndDiagnosticsForTest<AwaitExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4892,14 +4892,6 @@ lElseClause:
getResult = BadExpression(node, ErrorTypeSymbol.UnknownResultType).MakeCompilerGenerated()
End If

Dim resultType As TypeSymbol

If bindAsStatement Then
resultType = GetSpecialType(SpecialType.System_Void, node, diagnostics)
Else
resultType = getResult.Type
End If

If Not hasErrors Then
diagnostics.AddRange(allIgnoreDiagnostics)
End If
Expand All @@ -4909,7 +4901,7 @@ lElseClause:
Return New BoundAwaitOperator(node, operand,
awaitableInstancePlaceholder, getAwaiter,
awaiterInstancePlaceholder, isCompleted, getResult,
resultType, hasErrors)
type:=getResult.Type, hasErrors)
Copy link
Contributor

@AlekseyTs AlekseyTs Apr 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getResult.Type

It will be good to have a test for a scenario when we are awaiting a Task rather than a Task(Of T). #Closed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also it would be good to test the effect of this change on an await in a Sub expression lambda.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a scenario when we are awaiting a Task rather than a Task(Of T).

I think TestAwaitExpression (first test in that file) covers that.

an await in a Sub expression lambda.

Can you clarify what you'd like this test to verify? Just the IOperation node for the await in statement in lambda, or something else?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify what you'd like this test to verify? Just the IOperation node for the await in statement in lambda, or something else?

Emit, execution, optionally IOperation.

End Function

Private Shared Function DiagnosticBagHasErrorsOtherThanObsoleteOnes(bag As DiagnosticBag) As Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.

Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic

Partial Friend Class BoundAwaitOperator

#If DEBUG Then
Private Sub Validate()
Debug.Assert(Type.Equals(GetResult.Type) OrElse Type.SpecialType = SpecialType.System_Void)
Debug.Assert(Type.Equals(GetResult.Type))
End Sub
#End If

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ Class C
End Class]]>.Value

Dim expectedOperationTree = <![CDATA[
IAwaitOperation (OperationKind.Await, Type: System.Void, IsInvalid) (Syntax: 'Await UndefinedTask')
Expression:
IAwaitOperation (OperationKind.Await, Type: ?, IsInvalid) (Syntax: 'Await UndefinedTask')
Expression:
IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'UndefinedTask')
Children(0)
]]>.Value
Expand Down Expand Up @@ -134,8 +134,8 @@ Class C
End Class]]>.Value

Dim expectedOperationTree = <![CDATA[
IAwaitOperation (OperationKind.Await, Type: System.Void, IsInvalid) (Syntax: 'Await i')
Expression:
IAwaitOperation (OperationKind.Await, Type: ?, IsInvalid) (Syntax: 'Await i')
Expression:
IParameterReferenceOperation: i (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'i')
]]>.Value

Expand All @@ -162,8 +162,8 @@ Class C
End Class]]>.Value

Dim expectedOperationTree = <![CDATA[
IAwaitOperation (OperationKind.Await, Type: System.Void, IsInvalid) (Syntax: 'Await')
Expression:
IAwaitOperation (OperationKind.Await, Type: ?, IsInvalid) (Syntax: 'Await')
Expression:
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid) (Syntax: '')
Children(0)
]]>.Value
Expand Down Expand Up @@ -211,5 +211,115 @@ BC30800: Method arguments must be enclosed in parentheses.

VerifyOperationTreeAndDiagnosticsForTest(Of ExpressionStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True)
End Sub

<CompilerTrait(CompilerFeature.IOperation)>
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67616")>
Public Sub TestAwaitExpression_InStatement()
Dim source = <![CDATA[
Imports System.Threading.Tasks

Public Module Program
Public Async Function M() As Task(Of Integer)
Await M2()'BIND:"Await M2()"
Return 0
End Function

Public Function M2() As Task(Of String)
Throw New System.Exception()
End Function
End Module
]]>.Value

Dim expectedOperationTree = <![CDATA[
IAwaitOperation (OperationKind.Await, Type: System.String) (Syntax: 'Await M2()')
Expression:
IInvocationOperation (Function Program.M2() As System.Threading.Tasks.Task(Of System.String)) (OperationKind.Invocation, Type: System.Threading.Tasks.Task(Of System.String)) (Syntax: 'M2()')
Instance Receiver:
null
Arguments(0)
]]>.Value

Dim expectedDiagnostics = String.Empty

VerifyOperationTreeAndDiagnosticsForTest(Of AwaitExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True)
End Sub

<CompilerTrait(CompilerFeature.IOperation)>
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67616")>
Public Sub TestAwaitExpression_InStatement_InSubLambda()
Dim source = <compilation>
<file name="c.vb"><![CDATA[
Imports System
Imports System.Threading.Tasks

Public Module Program
Public Sub Main()
Dim lambda As Action = Async Sub()
Await M2()'BIND:"Await M2()"
End Sub
Copy link
Contributor

@AlekseyTs AlekseyTs Apr 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't an expression lambda though. And expression lambda would look like

Async Sub() Await M2()

Let's keep this scenario too. #Closed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep this scenario too.

Here I was referring to the body of the lambda rather than to the error.


lambda()
End Sub

Public Function M2() As Task(Of String)
System.Console.WriteLine("M2")
Return Task.FromResult("")
End Function
End Module
]]></file>
</compilation>

Dim expectedOperationTree = <![CDATA[
IAwaitOperation (OperationKind.Await, Type: System.String) (Syntax: 'Await M2()')
Expression:
IInvocationOperation (Function Program.M2() As System.Threading.Tasks.Task(Of System.String)) (OperationKind.Invocation, Type: System.Threading.Tasks.Task(Of System.String)) (Syntax: 'M2()')
Instance Receiver:
null
Arguments(0)
]]>.Value

Dim expectedDiagnostics = String.Empty

VerifyOperationTreeAndDiagnosticsForTest(Of AwaitExpressionSyntax)(source.Value, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True)
CompileAndVerify(source, expectedOutput:="M2", useLatestFramework:=True)
End Sub

<CompilerTrait(CompilerFeature.IOperation)>
<Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67616")>
Public Sub TestAwaitExpression_InStatement_InSubWithExpressionLambda()
Dim source = <compilation>
<file name="c.vb"><![CDATA[
Imports System
Imports System.Threading.Tasks

Public Module Program
Public Sub Main()
Dim lambda As Action = Async Sub() Await M2()'BIND:"Await M2()"

lambda()
End Sub

Public Function M2() As Task(Of String)
System.Console.WriteLine("M2")
Return Task.FromResult("")
End Function
End Module
]]></file>
</compilation>

Dim expectedOperationTree = <![CDATA[
IAwaitOperation (OperationKind.Await, Type: System.String) (Syntax: 'Await M2()')
Expression:
IInvocationOperation (Function Program.M2() As System.Threading.Tasks.Task(Of System.String)) (OperationKind.Invocation, Type: System.Threading.Tasks.Task(Of System.String)) (Syntax: 'M2()')
Instance Receiver:
null
Arguments(0)
]]>.Value

Dim expectedDiagnostics = String.Empty

VerifyOperationTreeAndDiagnosticsForTest(Of AwaitExpressionSyntax)(source.Value, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True)
CompileAndVerify(source, expectedOutput:="M2", useLatestFramework:=True)
End Sub
End Class
End Namespace