-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Direct representation of higher-kinded types #1343
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
Conversation
There are two areas that should be investigated further:
But the commit as is is ready for review. |
@@ -1641,6 +1641,7 @@ object SymDenotations { | |||
*/ | |||
def isCachable(tp: Type): Boolean = tp match { | |||
case _: TypeErasure.ErasedValueType => false | |||
case tp: TypeRef if tp.symbol.isClass => true |
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.
down to 22secs from 60secs with this change.
Now, need to do something with compareAliasedRefined
to get back to 2.5secs.
There are some loose ends with support for "existential types", which can be encoded using a combination of hk applications and wildcards. E.g.
can be encoded as
Subtyping and some other basic functionality works over these types, but other things crash the
with |
Was playing with how much does removing |
82c0026
to
f93a975
Compare
The PR is completed now as far as I am concerned. I mean to come back to named parameters, which would also affect |
* or -1 if no such parameter exists. | ||
/** Is entry associated with `pt` removable? This is the case if | ||
* all type parameters of the entry are associated with type variables | ||
* which have its `inst` fields set. |
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.
their inst
fields
Use (cached) superType where possible.
Beta-reduce only if `Config.simplifyApplications` is true. Turning off beta-reduction revealed two problems which are also fixed in this commit: 1. Bad treatement of higher-kinded argyments in cyclicity checking 2. Wrong variance for higher-kinded arguments in TypeAccumulator
As far as I can see we should now have feature parity with Scala 2.x with SI-2712. |
else if (tparam.paramVariance == 0) variance = 0 | ||
val pvariance = tparam.paramVariance | ||
if (pvariance < 0) variance = -variance | ||
else if (pvariance == 0) variance = 0 |
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.
variance *= tparam.paramVariance
instead of the if/else
? (Same in the case below)
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.
Great minds think alike :-) See next commit.
We decided to wait with several other PRs until this is in, so I want to merge by the end of the day, unless something important comes up. |
lazy val typeParams: List[LambdaParam] = | ||
paramNames.indices.toList.map(new LambdaParam(this, _)) | ||
|
||
def derivedTypeLambda(paramNames: List[TypeName] = paramNames, paramBounds: List[TypeBounds] = paramBounds, resType: Type)(implicit ctx: Context): Type = |
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.
Every other derivedFoo
method returns a Foo
, but this one may return a TypeAlias
or a TypeBounds
instead of a TypeLambda
, why is that? Could a different name be chosen to avoid confusion?
More bound checks are needed, this shouldn't compile: class Foo[A]
class Bar[B]
object Test {
type Alias[F[X] <: Foo[X]] = F[Int]
val x: Alias[Bar] = new Bar[Int] // Bar[X] is not a subtype of Foo[X]
} |
@@ -850,6 +879,12 @@ object Types { | |||
case _ => this | |||
} | |||
|
|||
/** If this is a TypeAlias type, its alias, otherwise this type itself */ | |||
final def followTypeAlias(implicit ctx: Context): Type = this match { |
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.
This method is never called
Also tests/pos-scala2/t2994.scala:23: error: type s takes type parameters
trait curry[n[_, _], s[_]] { type f[z <: NAT] = n[s, z] }
^ I think we should follow scalac here and enforce kind-correctness, for reference, the change to |
Previous logic could only handle classes as constructors. Also, address other reviewers comments.
a6b6c08
to
82fc27f
Compare
Better, but I can still break it :) class Foo[A]
class Bar[B]
object Test {
type Alias[F[X] <: Foo[X]] = F[Int]
def foo[M[_[_]], A[_]]: M[A] = null.asInstanceOf[M[A]]
val x = foo[Alias, Bar]
}
error: type arguments [Bar] do not conform to type Alias's type parameter bounds [F[X] <: Foo[X]]
val x = foo[Alias, Bar]
^ |
Interestingly, |
Enable checking of bounds when comparing type lambdas. This invalidates a pattern used in t2994 and potentially other code, where a bound [X] -> Any is used as a template that is a legal supertype of all other bounds. The old behavior is still available under language:Scala2.
@smarter Bounds check is tigthened now "at the source", in a different way from how it's done in Scala-2. The alternative would have been to open a loophole by not comparing bounds of type lambdas and then fixing it by checking all * types for bound correctness. But as you noted that would have to include all types computed by typer, not just types written by the programmer. I am scared this would be too expensive and that error messages would suffer. scalac seems to check inferred types of declared values and methods, but not other types. I agree this is not enough. |
Yes, I was skeptical about that loophole too, would be interesting to figure out how much code relies on it. A proper migration warning seems tricky indeed, but maybe we could have a flag in the constraint set |
Going to merge now to let other PRs proceed. Many thanks to @smarter for the thorough review! |
Hooray! 🌟 🎆 🎆 🎆 ⭐ |
On Fri, Jul 15, 2016 at 11:03 AM, Guillaume Martres <
Prof. Martin Odersky |
Rebased version of #1337 with commits squashed so that there are less than 100 commits in the PR.
This is (hopefully the last) attempt to model higher-kinded types in dotty. This time it's done directly, having specific types for type lambdas and higher-kinded applications.
This PR is based on #1282 but undoes most of it. Nevertheless I thought it would be good to have a trace of the history how we arrived here.