Skip to content

Enable nullable reference types for generated code#37758

Merged
sharwell merged 27 commits intodotnet:masterfrom
sharwell:nullable-syntax
Oct 7, 2019
Merged

Enable nullable reference types for generated code#37758
sharwell merged 27 commits intodotnet:masterfrom
sharwell:nullable-syntax

Conversation

@sharwell
Copy link
Contributor

@sharwell sharwell commented Aug 6, 2019

Review commit-by-commit is recommended.

@sharwell
Copy link
Contributor Author

sharwell commented Aug 6, 2019

@dotnet/roslyn-compiler the build errors are caused by a conflict with db84d66 that occurred in parallel. That change was arguably a breaking API change (inputs that were previously allowed now throw exceptions, even though the impacted source code is not valid C# code). The easiest way to address the code generation issue is to revert the change. Otherwise, I need to figure out how to make a non-nullable Update method override a nullable Update method.

/cc @CyrusNajmabadi

@CyrusNajmabadi
Copy link
Contributor

@dotnet/roslyn-compiler the build errors are caused by a conflict with db84d66 that occurred in parallel. That change was arguably a breaking API change (inputs that were previously allowed now throw exceptions

Could you give an example of an input that was previously allowed that we would want to keep allowing?

@jcouv jcouv added the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Aug 9, 2019
@sharwell sharwell marked this pull request as ready for review August 12, 2019 22:10
@sharwell sharwell removed the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Sep 23, 2019
@sharwell sharwell requested a review from a team as a code owner September 23, 2019 17:53
@sharwell
Copy link
Contributor Author

@dotnet/roslyn-compiler this is ready for review

WriteLine(" var {0} = ({1})this.Visit(node.{2});", CamelCase(field.Name), field.Type, field.Name);
if (!IsOptional(field) && field.Type != "SyntaxToken")
{
WriteLine(" var {0} = ({1})this.Visit(node.{2}) ?? throw new ArgumentNullException(\"{0}\");", CamelCase(field.Name), GetFieldType(field, green: false), field.Name);
Copy link
Member

Choose a reason for hiding this comment

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

{1} [](start = 60, length = 3)

This cast ends up coming out as ? often, which is wrong. We should not be trying to cast to a nullable reference type and throwing if it's null.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What form would you suggest instead?

Copy link
Member

@333fred 333fred Sep 26, 2019

Choose a reason for hiding this comment

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

The generated cast should not have a ? in it (for reference types, if casting to an NVT of course it needs one).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So to clarify, you want this?

-(T?)Method() ?? throw ...
+(T)(Method() ?? throw ...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should not be trying to cast to a nullable reference type and throwing if it's null.

FWIW, this is exactly what we do today, you just can't see it in the code.

Copy link
Member

Choose a reason for hiding this comment

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

That's correct. And more accurately, we cast to a regular reference type and throw if it was null.

Copy link
Contributor Author

@sharwell sharwell Sep 26, 2019

Choose a reason for hiding this comment

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

➡️ Since this is a cosmetic change only, I'm going to file this as a follow-up issue to clean up the generated code for this case.

@333fred
Copy link
Member

333fred commented Sep 24, 2019

Done review pass (commit 24)

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

LGTM (commit 26). @dotnet/roslyn-compiler for a second review.

@RikkiGibson
Copy link
Member

We need a senior compiler review @dotnet/roslyn-compiler

else
{
WriteLine(" var {0} = ({1})this.Visit(node.{2});", CamelCase(field.Name), field.Type, field.Name);
if (!IsOptional(field) && field.Type != "SyntaxToken")
Copy link
Contributor

Choose a reason for hiding this comment

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

field.Type != "SyntaxToken" will always be true since the previous if-check checks for "SyntaxToken" already.

else
{
Write("{0} == null ? null : (Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.{1}){0}.Green", CamelCase(field.Name), field.Type);
if (IsAnyList(field.Type) || IsOptional(field))
Copy link
Contributor

Choose a reason for hiding this comment

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

IsAnyList would already have been covered by the if-checks above, right?

@333fred
Copy link
Member

333fred commented Oct 7, 2019

@dotnet/roslyn-compiler for a second review please.

@jcouv jcouv self-assigned this Oct 7, 2019
@jcouv
Copy link
Member

jcouv commented Oct 7, 2019

I'll look today

@jcouv
Copy link
Member

jcouv commented Oct 7, 2019

Oh, never mind, I see that we have two reviews already.

@jcouv jcouv added this to the 16.4.P3 milestone Oct 7, 2019
@sharwell sharwell merged commit 67021b4 into dotnet:master Oct 7, 2019
@sharwell sharwell deleted the nullable-syntax branch October 7, 2019 21:05
@CyrusNajmabadi
Copy link
Contributor

Awesome!

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.

8 participants