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

VM doesn't consider dynamic == Object. #33768

Open
lrhn opened this issue Jul 6, 2018 · 5 comments
Open

VM doesn't consider dynamic == Object. #33768

lrhn opened this issue Jul 6, 2018 · 5 comments
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@lrhn
Copy link
Member

lrhn commented Jul 6, 2018

Type objects should be equal if the types are sub-types of each other. That is, when the types are indistinguishable wrt. subtyping.

That includes dynamic, Object, and void all being equal when compared as Type objects at run-time.

Example:

main() {
  print(dynamic == Object);  // prints false, should print true.
}
@lrhn lrhn added web-dart2js type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. and removed web-dart2js labels Jul 6, 2018
@rmacnak-google
Copy link
Contributor

Reflection requires these to be distinct.

@natebosch
Copy link
Member

Is this expectation part of the spec - does the spec need to be updated?

Does DDC have the same behavior as VM (it looks like dart2js does have the same behavior).

@lrhn
Copy link
Member Author

lrhn commented Jul 16, 2018

There is no specification of Type.operator== apart from what it says in the SDK declaration. There is also no specification of what Type object means except that they "represent" a run-time type. The spec is silent except for creating Type objects representing types when you use a type expression as an expression.

For the equality to be useful, type objects representing the same type must be equal.
Type objects representing distinguishably different types should be different.

The issue here is that at run-time, there is nothing distinguishing dynamic and Object as types. Any object is an instance of both. Any type is a sub-type of both, even each other. The two types are not distinguishable.

Or, put differently, the idea is that dynamic is not a type at run-time at all, it exists entirely in the static type system. At run-time, there is only Object, and dynamic is just Object-with-a-flag, and the flag only exists in the static type system.

We would keep the dynamic flag around in order to display types for debugging, but it really is just Object, and hence the Type object for the type is a Type object representing Object and equal to any other such.

With that design, reflection does not need to distinguish because at run-time there is nothing to distinguish, it's all Object.

@leafpetersen @eernstg

@eernstg
Copy link
Member

eernstg commented Mar 14, 2019

@natebosch wrote:

Is this expectation part of the spec - does the spec need to be updated?

No, the spec requires that two reified types t1 and t2 satisfy t1 == t2 whenever t1 <: t2 and t2 <: t1.

@rmacnak-google wrote:

Reflection requires these to be distinct

It is still possible for an implementation to make a distinction between the reification of a type written as dynamic and a type written as Object (and void, too), even though they must be considered equal according to operator == at run time, because they are not required to be identical. This is motivated by the wish to use the names that occur in the source code for error messages and stack traces.

Reflective operations would be able to use identical to make this distinction (assuming that canonicalization of reified types is similar to everybody's expectations, cf. dart-lang/language#95), and so I believe that there is no conflict in this area.

@lrhn
Copy link
Member Author

lrhn commented Jul 12, 2019

The "equal if mutual subtypes" rule also affects other cases than top types (all, unsurprisingly, related to union types):

  • FutureOr<Object> and Object,
  • FutureOr<Future<Object>> and Future<Object>, (etc.)
  • FutureOr<Null> and Future<Null>
    and any composite type where such equal types occur in the corresponding places.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

4 participants