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

Null propagation expression does not allow ! as a nested operator form (VS 16.8, .NET 5) #3393

Open
agocke opened this issue Apr 24, 2020 · 8 comments
Assignees
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion
Milestone

Comments

@agocke
Copy link
Member

agocke commented Apr 24, 2020

See dotnet/docs#17988

This means that the only correct parse of

var x = a?.b.c!.d.e;

is (a?.b.c)!.d.e, which prevents usage of null-forgiving in a chain of null-propagating accesses. To remedy this we could accept ! as an optional token after every simple name in the null-propagating non-terminal.

cc @jcouv @gafter


Was discussed in LDM 6/17/2020. There is agreement/support, but we'll need to investigate and make a concrete syntax proposal. Also, there is desire to keep terminal ! parsing as today: a?.b.c! would still parse as (a?.b.c)!.
For reference, the current syntax.

@AntonLapounov
Copy link
Member

I was not aware of this issue and filed dotnet/roslyn#43659.

@RikkiGibson
Copy link
Contributor

It doesn't feel like accepting an optional token after a simple name is sufficient for a case like Prop?.Method1()!.Method2(). Could we solve this by considering !. a distinct operator which accesses a member and suppresses the nullable warning on the receiver?

@jaredpar
Copy link
Member

Looks like the NRT Spec needs to be updated. Presently it says

The postfix ! operator has no runtime effect - it evaluates to the result of the underlying expression. Its only role is to change the null state of the expression, and to limit warnings given on its use.

That is not true though cause it changes the manner in which conditional expressions are parsed hence their runtime behavior. Here is a simple sharplab sample that demonstrates this.

@333fred
Copy link
Member

333fred commented Aug 24, 2020

Well, that's how it should be. This is a bug that we need to fix.

@gafter
Copy link
Member

gafter commented Aug 25, 2020

That is not true though cause it changes the manner in which conditional expressions are parsed hence their runtime behavior.

Yes. Also parentheses have runtime behavior for the same reason.

@RikkiGibson
Copy link
Contributor

If nobody has written a syntax proposal for this I would be happy to take a stab at it.

@333fred
Copy link
Member

333fred commented Aug 26, 2020

@RikkiGibson iirc https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#null-conditional-operator is the place we need to adjust: specifically, null_conditional_operations need to be expanded.

@MadsTorgersen
Copy link
Contributor

The initial example was not supposed to parse; it's a bug that we accept it at all:

var x = a?.b.c!.d.e;

The reason is that ! is only supposed to apply to a primary_expression, and a?.b.c isn't a primary_expression but a unary_expression.

So in a sense, the fact that we accept this in C# 8.0 is a bug. However, I do agree that we should give it sensible semantics. We could enhance the grammar as follows:

null_conditional_expression
    : primary_expression null_conditional_operations_no_suppression suppression?
    ;

null_conditional_operations_no_suppression
    : null_conditional_operations? '?' '.' identifier type_argument_list?
    | null_conditional_operations? '?' '[' argument_list ']'
    | null_conditional_operations '.' identifier type_argument_list?
    | null_conditional_operations '[' argument_list ']'
    | null_conditional_operations '(' argument_list? ')'
    ;

null_conditional_operations
    : null_conditional_operations_no_suppression suppression?
    ;

suppression
    : '!'
    ;

The semantics then are that the "interior" !s get folded into the semantic "desugaring" of the null conditional expression, and have whatever effects they have on warnings there. But a top-level trailing ! is a different beast and gets applied to the whole null conditional expression, changing its null state.

@jcouv jcouv modified the milestones: 9.0 candidate, 9.0 Sep 18, 2020
@333fred 333fred added the Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification label Oct 16, 2020
@jcouv jcouv changed the title Null propagation expression does not allow ! as a nested operator form Null propagation expression does not allow ! as a nested operator form (VS 16.8, .NET 5) Nov 4, 2020
@jcouv jcouv moved this to Done Umbrellas in Compiler: Julien's umbrellas Jun 3, 2024
@dotnet dotnet locked and limited conversation to collaborators Nov 19, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion
Projects
Status: Done Umbrellas
Development

No branches or pull requests

8 participants