-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Improve opaque types #6567
Improve opaque types #6567
Conversation
Why class scope and not any nearest scope? |
They are the same, since opaque types will only be allowed to be defined as members of classes, objects and traits. The restriction is there because it gives us an elegant way to encode opaque types as abstract types. |
Then will the enclosing class form the implicit scope of the opaque type? Or will you have to explicitly import its extension methods every time you use it? |
6b50086
to
5ffb902
Compare
Yes. In fact, that's already the case today. We simply drop the rule that opaque types have companion objects. |
a8eb777
to
71f8413
Compare
An important semantic change of this PR affects comparisons of opaque types. Previously we had for any type object m {
type T
} that object m {
opaque type T = Int
} Inside |
e52a757
to
f4b2c9a
Compare
f4b2c9a
to
2648718
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM, comments are minor nitpicks or spotted typos.
The previous treatment would be incompatible with the new opaque types scheme.
We skip a package object if we look for a term, but consider it if we look for a type. That way we can handle at the same time overloaded terms in several source files and opaque types.
With the changes in Typer, it is now possible that a type `T` that is a member of some package object `pobj` in a package `p` is seen once as `p.pobj.T` and then also as `p.T`. Type comparer has to make sure that these two types are seen as equivalent.
This is a template for checking the other flags as well (e.g. the outstanding problem how to check the `enum` flag could be solved like this.
The scope where an opaque alias is transparent is now the enclosing class of the opaque definition. The notion of opaque companion object has been dropped.
The missing case was discovered while experimenting with different opaque type encodings. It has nothing to do with opaque types, just with the fact that we sometimes got a UniqueRefDenotation instead of a SymDenotation. But this should not make a difference.
Previously we had for any type `T` in ``` object m { type T } ``` that `m.this.T =:= m.T` as long as we are inside object `m` (outside, `m.this.T` makes no sense). Now, assume `T` is an opaque type. ``` object m { opaque type T = Int } ``` Inside `m` we have `this.m.T =:= Int`. Is it also true inside `m` that `m.T =:= Int`? Previously, we said no, which means that subtyping and =:= equality were not transitive in this case. We now say yes. We achieve this by lifting the external reference `m` to `m.this` if we are inside object `m`. An example that shows the difference is pos//opaque-groups-params.scala compiled from Tasty.
It turns out we get confused when we call normalizeOpaque as part of normal completion during computeDenot. Fine tuning normalizeOpaque and calling it in the window of vulnerability where a type is Opaque but not yet Deferred fixes the problem. Before the following tests failed when compiled from-tasty: tests/run/implicit-specifity.scala failed tests/pos/i5720.scala failed tests/pos/toplevel-opaque-xm failed tests/pos/postconditions.scala failed
Make parameter definitions in DefDef have the same span as the symbols they define. Previously, this position was not set, which means it would be set pretty much in an ad-hoc way based on the positions that were set in the definitions environment. For some reason I cannot quite reconstruct, the changes to opaque caused pos/exports.scala to fail pickling tests because an extension parameter symbol symbol a different position after pickling.
2648718
to
44b9562
Compare
This is an experimental PR to see whether we can make opaque types more useful and (hopefully) simpler to implement.
Planned work:
opaque
as a local modifierThe original motivation for this work was to arrive at a better implementation of
FlagSet
in the dotty compiler. What I would like to have:Flags
:Flag
,FlagSet
, andFlagChoice
, all implemented asLong
.Flag <: FlagSet
,Flag <: FlagChoice
and no relationship betweenFlagSet
andFlagChoice
.This would make existing patterns of flag usage safer and less confusing, while also increasing their efficiency.