Issue 17891 in dart: A value of type 'void' cannot be assigned to a variable of type 'Object'

170 views
Skip to first unread message

da...@googlecode.com

unread,
Mar 28, 2014, 3:09:35 PM3/28/14
to bu...@dartlang.org
Status: New
Owner: ----
Labels: Type-Defect Priority-Unassigned

New issue 17891 by andrew.m...@gmail.com: A value of type 'void' cannot be
assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

void main() {
print(foo());
Object a = foo();
}

void foo() => null as dynamic;

The argument type 'void' cannot be assigned to the parameter type 'Object'
A value of type 'void' cannot be assigned to a variable of type 'Object'

What means 'cannot be assigned'?
This code run in checked mode without errors.

This means that the message 'cannot be assigned' is wrong.
This is because it can be assigned.

I think that for 'void' type the messages must be different than for other
types.

In C# Void type (struct Void) is a subtype of the Object.
But at the same time in C# allowed using 'Void' only as the return type for
a method.

In Dart 'void' method returns 'null'.
I think that the message must notify about possible misuse of the result
of 'void' method call.


--
You received this message because this project is configured to send all
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

da...@googlecode.com

unread,
Mar 28, 2014, 8:18:33 PM3/28/14
to bu...@dartlang.org
Updates:
Status: Triaged
Labels: Area-Language

Comment #1 on issue 17891 by floi...@google.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

Assigning to language.

dart2js correctly flags this as "not assignable".

da...@googlecode.com

unread,
Mar 29, 2014, 2:43:14 AM3/29/14
to bu...@dartlang.org

Comment #2 on issue 17891 by andrew.m...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

Try this code here: http://try.dartlang.org

void main() {
print(foo());
Object obj = foo();
}

void foo() {}

This code does not produce warnings. But must to produce.
print(foo());

This code produce correct warning.
Warning: Expression does not yield value.

The Dart VM produce incorrect warning in both cases.
This is because method with 'void' return type does not returns values
with 'void' types.
The 'void' type used only to indicate that the method does not return any
explicitly specified value (i.e. it does not return anything, that can be
expected).

Instead it implicitly returns the `null` value and this case (expecting
return value) are always unpredictable if it goes (returned) from
the 'void' method and assumed that the method explicitly! returns value
(including `null` value).

So, I thik that the messages such "type 'void' cannot be assigned to" look
very ridiculous.

Dart is not the first programming language in the world and we all know
that the `void` type used only as the indicator but not as the real type of
returned value.

da...@googlecode.com

unread,
Mar 31, 2014, 1:38:14 PM3/31/14
to bu...@dartlang.org

Comment #3 on issue 17891 by caitpott...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

I was bored and decided to hack on this, I haven't been writing enough
native code lately!

This is pretty crap so far and only really handles a small subset of the
desired functionality, patch is at https://codereview.chromium.org/219773002

Support for instance methods and assignment to other properties are the
remaining pieces, but I want to get some feedback on the initial
implementation before I add that.

da...@googlecode.com

unread,
Mar 31, 2014, 2:30:01 PM3/31/14
to bu...@dartlang.org

Comment #4 on issue 17891 by andrew.m...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

More precisely, the pronlem in that the "Likewise, passing the result of a
void method as a parameter or assigning it to a variable will cause a
warning unless the variable/formal parameter has type dynamic".

I don't think that warning must be a common warning about the type
compatibilty such a "type 'void' cannot be assigned to ...".

This is because "The special type void may only be used as the return type
of a function: it is a compile-time error to use void in any other context".

This means that you cannot correct an error such a "A value of type 'void'
cannot be assigned to a variable of type 'Object'" via this adaption.

Before:
Object a = foo();

After:
void a = foo();

Another problem in that the dart2js also implemented not correctly and does
not conforms to Dart language spec (ECMA-52?).

void main() {
Object obj1 = foo();
dynamic obj = foo();
}

dart2js produce warning for this expression:

dynamic obj = foo();
Warning: Expression does not yield value.

Accordingly language spec:

- passing the result of a void method as a parameter or assigning it to a
variable will cause a warning unless the variable/formal parameter has type
dynamic.

In our case "variable parameter has type dynamic" and here there should be
a warning because (from language spec):

void <: void(by reflexivity)
bottom <: void (as bottom is a subtype of all types).
void <: dynamic (as dynamic is a supertype of all types)

This states that the "void" implements "dynamic" and subtype of "dynamic"
can be assigned to "dynamic".

dynamic obj = foo();

But dart2js not take into account this language rule.

P.S.

And I very much doubt that dart2js will pass the certification to the
ECMA-52 with this incompatibility with language specification

da...@googlecode.com

unread,
Mar 31, 2014, 2:31:44 PM3/31/14
to bu...@dartlang.org

Comment #5 on issue 17891 by andrew.m...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

typo:

In our case "variable has type dynamic" and here should NOT be a warning
because (from language spec):

da...@googlecode.com

unread,
Mar 31, 2014, 2:58:36 PM3/31/14
to bu...@dartlang.org

Comment #6 on issue 17891 by andrew.m...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

Accordingly language spec if method has void type this not means that it
does not return nothing.
So this means, that warning such a "Expression does not yield value" are
not correct because:
- On the other hand, it is possible to return the result of a void method
from within a void method.
- One can also return null; or a value of type dynamic.
- In checked mode, a dynamic type error would arise if a non-null object
was returned from a void method (since no object has runtime type dynamic).

Here is a proof. Production mode.

void main() {
print(foo());
}

void foo() { return 5 as dynamic; }

Output:
5

This means that void method in Dart always return value.
In checked mode it can only return null.
In production mode any value with dynamic type.

Another proof (checked mode):

void main() {
Function f = foo;
print("Result that return 'void foo()': ${f()}");
}

void foo() { }

Output:
Result that return 'void foo()': null

This means that void method in Dart always yield value.

da...@googlecode.com

unread,
Mar 31, 2014, 4:38:14 PM3/31/14
to bu...@dartlang.org

Comment #7 on issue 17891 by caitpott...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

I don't think it makes sense to prevent this from working in production
mode, however there is no problem currently when type checking is enabled,
and I do agree that that's a problem.

It would be helpful if you could take a look at the patch and offer some
suggestions on improving it, since as I said it only covers a small portion
of what we want it to do, at this time.

For instance, since this is happening in the Parser (in my patch), is the
static call's function guaranteed to be parsed and exist in the VM by the
time the analysis happens? How would you extend this for instance method
calls and static function calls, since I'm not totally sure how this
introspection would work, or how expensive it would be (and, for that
matter, if that introspection is even possible during parsing). Short of
that, extending this to also work for assignment operations should be
simple.

da...@googlecode.com

unread,
Apr 1, 2014, 1:26:08 AM4/1/14
to bu...@dartlang.org

Comment #8 on issue 17891 by andrew.m...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

>> It would be helpful if you could take a look at the patch and offer some
>> suggestions on improving it, since as I said it only covers a small
>> portion of what we want it to do, at this time.

Your patch not looks inside the problem. It are not correct.

Problem in the (hard) language design.

Method that has the 'void' return type in Dart ALWAYS return a value.
This is a mistake to believe that in Dart some expression may not yield
value.

Method that has the 'void' return type is able to return value.
If it able to return value it always return value even it is not specified.
In Dart the default value for all object are "null" (bottom).

But at the same time:
- The name void does not denote a Type object.
- No instance ever has type void

So, in this case how we can display some warnings if "void" does not denote
a Type object and no instance ever has type void?

Example:
"A value of type 'void' cannot be assigned to a variable of type 'Object'"

This is the same as you warning "Train that can't swim underwater can not
run into space".

All type checks in Dart MUST know about special types such a 'void'.

They MUST take into account that these types does not denote a Type object
and no instance ever has these types.

How possible check types that denote type object with types that DOES NOT
denote type object?

Warning about type incompatibility in this case are not correct.
Instead of this message:
A value of type 'void' cannot be assigned to a variable of type 'Object'

Must be (because void does not denote a Type object):

The 'void' type cannot has instance and cannot be assigned to a variable of
type 'Object'.
The 'void' type does not denote type and cannot be assigned to a variable
of type 'Object'.

P.S.
But no one rule in Dart language spec states that void function does not
return (not yield) value.

da...@googlecode.com

unread,
Apr 1, 2014, 1:30:58 AM4/1/14
to bu...@dartlang.org

Comment #9 on issue 17891 by andrew.m...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

void main() {
// The 'void' type does not denote type and cannot be assigned to a
parameter of type 'Object'.
print(foo());
// // The 'void' type does not denote type and cannot be assigned to a
variable of type 'Object'.
Object obj = foo();

da...@googlecode.com

unread,
Apr 1, 2014, 8:54:43 AM4/1/14
to bu...@dartlang.org

Comment #10 on issue 17891 by caitpott...@gmail.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
http://code.google.com/p/dart/issues/detail?id=17891

Well, not quite...

So, by definition, a "void" expression is an expression whose result does
not have a value.

It is true that it will technically return a value anyways, but being a
void function, one should not attempt to use that result.

In older C compilers (certain versions of MSVC come to mind), using a void
result as a parameter to a function call would not actually cause an error,
but undefined behaviour. In order to prevent this undefined behaviour,
static analysis of the parse trees are used to prevent this.

So as you've correctly pointed out, a void function is inconsistently
assignable (and thus sometimes yields a result, for dynamic types), and
sometimes yields an error. The fact is, this should always yield an error,
because a void result type's value is, by definition, undefined. Throwing
an error during static analysis is the correct way to clean this up.

I think that perhaps we are seeing this problem in two different ways, but
I'm aiming to prevent inadvertent inclusion of undefined behaviour in a
production application.

da...@googlecode.com

unread,
Aug 26, 2014, 6:26:09 PM8/26/14
to bu...@dartlang.org
Updates:
Status: Invalid
Owner: gbra...@google.com

Comment #11 on issue 17891 by gbra...@google.com: A value of type 'void'
cannot be assigned to a variable of type 'Object'
https://code.google.com/p/dart/issues/detail?id=17891

(No comment was entered for this change.)
Reply all
Reply to author
Forward
0 new messages