Why a declaration doesn't give a CS0201 compiler error?

  • A+
Category:Languages

I am confused by the terminology of Compiler error CS0201. It says that

Only assignment, call, increment, decrement, and new object expressions can be used as a statement

So according to this anything except above cannot be a statement. Then how does below line does not produce the above error.

Anyclass obj; 

Here we don't have any assignment or call or increment or decrement or new object expression.

I know I am missing something as the official documentation contradicts this error by saying declaration is also a statement.


The error text is:

Only assignment, call, increment, decrement, and new object expressions can be used as a statement

Your question includes the assertion:

So according to this anything except above cannot be a statement.

No, that is an incorrect conclusion.

First of all, what you're doing is simply a bad idea. Do not read the error messages to learn what the rules of the language are. The error messages are there to tell you what's wrong with programs that are not legal. They are not intended to be a guide as to what is legal! Error messages are written assuming that the context is that you're looking at an illegal program at the same time as you are reading the error. Error messages are a single sentence; the language specification is 800 pages long and has a lot more detail. Read the specification.

Second: a correct conclusion is: according to that error message, no other expression can be used as a statement. This error message is only produced in contexts where there is an invalid expression being used in a context where a statement is expected.

Then how does below line does not produce the above error.

Anyclass obj; 

That line is not an expression, so the error message doesn't apply to it.

You made a wrong conclusion from this error message, which is evidence that this error message is confusing, and for that reason alone we could argue that it could be changed. For example, we could say "expression statement" instead of "statement". Or we could diagnose the larger problem, and report "This statement consists of an expression that is typically only useful for its value, which is discarded. Only increment...", and now the purpose of the message becomes more clear.

There are a great many error messages in C# that are confusing. For example, consider my personal favorite:

A params parameter must be the last parameter in a formal parameter list

If you didn't know how params parameters worked, it would be reasonable to conclude from this error message that (params int[] x, params int[] y) is legal -- after all, a params parameter is the last parameter in a formal parameter list! It would also be sensible to conclude that (int x) is wrong, because a params parameter is not the last parameter in that list!

Of course we know that what the error message means is "if you have a params parameter then that parameter must be the last one in the formal parameter list".

Error messages are one of the most important outputs of any compiler, and yet they are often confusing, ungrammatical, abstruse and unhelpful. Why is that?

  • Compiler writers are not English majors.
  • Compiler error messages are often written with the compiler writer's convenience in mind, not with the user's convenience. Example: I spent literally weeks improving overload resolution error message reporting logic for problems involving lambdas so that adding LINQ to C# 3 did not make the error messages misleading. That was a lot of work, and it took away effort that could have been spent on other work.
  • Compiler writers are domain experts who can find it difficult to get back into "beginner mind".

But hardest of all:

  • to write an error message, a compiler writer must imagine themselves to be in the mental state of someone who has made a mistake, and figure out what will remove the erroneous mental state in a manner that leads to a correct program being written. That's a hard problem in human psychology! Compiler writers are not mind readers, but they are asked to be all the time.

So what's happening here is: the compiler is expecting a statement. It found expression ; which looks like an expression statement. But only a subset of expressions are legal in an expression statement; if it is not one of those, then this error is reported.


If you have an idea for how an error message can be improved, please don't report it here; start a discussion on the Roslyn github forum.


Speaking of which: the error message you quote is wrong. It was never updated when await was added to the language. await x is an expression and await x; is legal.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: