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

enable main methods to be asynchronous #18157

Merged
merged 13 commits into from
Mar 31, 2017

Conversation

TyOverby
Copy link
Contributor

@TyOverby TyOverby commented Mar 24, 2017

This is the first chunk in enabling Async-Main. It merely concerns itself with deciding which methods have valid entrypoint signatures.

@@ -597,18 +597,47 @@ internal bool IsEntryPointCandidate

/// <summary>
/// Checks if the method has an entry point compatible signature, i.e.
/// - the return type is either void or int
/// - the return type is either void, int, Task, or Task&lt;int&gt;
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Mar 24, 2017

Choose a reason for hiding this comment

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

consider <see cref #Resolved

Copy link
Contributor Author

@TyOverby TyOverby Mar 24, 2017

Choose a reason for hiding this comment

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

Done #Resolved

}
else
{
return false;
Copy link
Member

Choose a reason for hiding this comment

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

is there a concern that ValueTask is not matched here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For now we are just supporting Task, however, the comments in this method describe how to (very easily) support any "task-like" object including ValueTask.

@TyOverby
Copy link
Contributor Author

@dotnet/roslyn-compiler This is now out for review.

@jcouv
Copy link
Member

jcouv commented Mar 24, 2017

Looks like there's a warning preventing build from succeeding:

15:54:32 Symbols\MethodSymbol.cs(601,27): warning CS1584: XML comment has syntactically incorrect cref attribute 'System.Threading.Tasks.Task{int}' [D:\j\workspace\windows_debug---f56cc009\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj]
15:54:33 
Symbols\MethodSymbol.cs(601,55): warning CS1658: Type parameter declaration must be an identifier not a type. See also error CS0081. [D:\j\workspace\windows_debug---f56cc009\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj]

@@ -1104,7 +1104,7 @@ internal enum ErrorCode
ERR_VarargsAsync = 4006,
ERR_ByRefTypeAndAwait = 4007,
ERR_BadAwaitArgVoidCall = 4008,
ERR_MainCantBeAsync = 4009,
// ERR_MainCantBeAsync = 4009,
Copy link
Member

Choose a reason for hiding this comment

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

Should we delete the corresponding resource string?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

return false;
}

if (!IsAsyncMainReturnType(returnType) && IsAsync)
Copy link
Member

Choose a reason for hiding this comment

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

We should add a test case for this too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Already had an async void test, I'll add an async int test too

{
return false;
}
// Change this to `namedType.IsNonGenericTaskType` if you want to support "task-like" objects.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: in general we don't break up if / else if structures with comments like this. Instead put them into the body, or add a meta comment to the local function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


class A
{
async static Task<float> Main()
Copy link
Member

Choose a reason for hiding this comment

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

Should add variants that check for async Task / Task<T> and have a Main(string[])

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@TyOverby
Copy link
Contributor Author

@jcouv Thanks! Should have it fixed by now.

@@ -597,18 +597,48 @@ internal bool IsEntryPointCandidate

/// <summary>
/// Checks if the method has an entry point compatible signature, i.e.
/// - the return type is either void or int
/// - the return type is either void, int, <see cref="System.Threading.Tasks.Task" />,
/// or <see cref="System.Threading.Tasks.Task{T}" /> Where T is an int.
Copy link
Member

Choose a reason for hiding this comment

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

Where [](start = 61, length = 5)

Nit: capitalization on "where"

Copy link
Contributor Author

@TyOverby TyOverby Mar 27, 2017

Choose a reason for hiding this comment

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

Done #Resolved

{
if (this.IsVararg)

bool IsAsyncMainReturnType(TypeSymbol type)
Copy link
Member

Choose a reason for hiding this comment

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

Should the new logic be conditional on language version?
If so, please add a test with language version 7.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Added a version of each of these tests that uses langversion 7

return false;
}

if (!IsAsyncMainReturnType(returnType) && IsAsync)
Copy link
Member

@jcouv jcouv Mar 27, 2017

Choose a reason for hiding this comment

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

IsAsyncMainReturnType(returnType) [](start = 17, length = 33)

Consider pulling IsAsyncMainReturnType(returnType) into a local. #Closed

Copy link
Contributor Author

@TyOverby TyOverby Mar 27, 2017

Choose a reason for hiding this comment

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

Done #Closed

// async static Task<float> Main()
Diagnostic(ErrorCode.WRN_InvalidMainSig, "Main").WithArguments("A.Main()").WithLocation(6, 30),
// error CS5001: Program does not contain a static 'Main' method suitable for an entry point
Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1) );
}
Copy link
Member

Choose a reason for hiding this comment

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

Consider adding a test without async (Main method returns a Task by hand).

Copy link
Member

Choose a reason for hiding this comment

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

Never mind, I see that you use string replacement to achieve that.


In reply to: 108235403 [](ancestors = 108235403)

@jcouv
Copy link
Member

jcouv commented Mar 27, 2017

            // (4,23): warning CS0028: 'A.Main(bool)' has the wrong signature to be an entry point

Makes me wonder if this diagnostic should provide more explicit directions about what is allowed (might be lengthy though).


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTests.cs:1429 in 3228961. [](commit_id = 3228961, deletion_comment = False)

}
}";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7));
compilation.VerifyDiagnostics(Diagnostic(ErrorCode.ERR_MainCantBeAsync, "Main").WithArguments("A.Main(string[])").WithLocation(6, 23));
Copy link
Member

Choose a reason for hiding this comment

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

If you use a C# 7 compiler but set language version = 6, using a C# 7 feature like tuples will give you a better error ("Please use C# 7").
Can we do the same here? Look at CheckFeatureAvailability method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

}

[Fact]
public void MainCanBeAsync()
Copy link
Member

Choose a reason for hiding this comment

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

Note: please add a test verifying we don't allow variants where main has a ref return.

static ref Task Main() { ... }

Context is that we incorrectly allow this for int today: #17923

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll cherry-pick your PR into my branch and add a test.

compilation.VerifyDiagnostics(
// (6,5): error CS8107: Feature 'async main' is not available in C# 7. Please use language version 7.1 or greater.
// async static Task Main(string[] args)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, @"async static Task Main(string[] args)
Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible for the diagnostic to point to a narrow piece of syntax? For example "Main" or maybe "async"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added a comment and will get back to this shortly

jaredpar and others added 2 commits March 30, 2017 15:37
Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM

Nit: I think the marker convention would be PROTOTYPE(async-main) for this branch, not just PROTOTYPE.

@TyOverby
Copy link
Contributor Author

I'm merging now even though the tests aren't done.

The tests were all passing and I only made a change to a comment.

@TyOverby TyOverby merged commit b3243e8 into dotnet:features/async-main Mar 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants