Skip to content

Change typeapply #994

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

Merged
merged 41 commits into from
Dec 15, 2015
Merged

Change typeapply #994

merged 41 commits into from
Dec 15, 2015

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Dec 6, 2015

Changes to arrive at a more tractable treatment of higher-kinded types.

It seems to complciate things with no real purpose.
Done in order to keep the basics as simple as possible.
Treating existentially bound parameters as still instantiatable type
parameters does not seem to add anything fundamental, and makes the
type system less regular.
Also: fix adaptArgs and LambdaTrait to make it work.
Also: fix EtaExpansion.
Also: Add some debug code to Applications, awaiting further fixes.
typeSymbols always have empty type parameter list.
Previous implementation died because
TermRef had no denotation.
Printing bounds omits the "<:" otherwise.
Arg bounds do not count is bindings.
Arg bounds do not count is bindings.
Also: TypeLambda's $Apply binding should be covariant,
because the parameter is (not sure it matters though).
Taking typeAlias is illegal in that case.
This prevents propagation changes leading to long
recompiles when a printer is changed.
/** Lambda abstract `self` with given type parameters. Examples:
*
* type T[X] = U becomes type T = [X] -> U
* type T[X] >: L <: U becomes type T >: L <: ([X] -> _ <: U)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean that we cannot refer to X in L ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, then this should be explicitly disallowed somewhere, currently the following:

class Test {
  type Foo[X] >: List[X]
}

Triggers an assertion: unresolved symbols: type X
On the other hand, couldn't we rewrite type T[X] >: L <: U as type T = [X] -> (_ >: L <: U) or something else to allow this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That means bounds can be lambdas (and lambdas are complex arrangements of refinements and references). So what was a TypeBounds type now becomes something very complicated. I am afraid to got there. If we had explicit type lambdas as a separate type it would take it under consideration. But then we need also explicit AppliedType types.

All Lambda abstractions, not just eta expansions, should
use actual parameter bounds, not the one retrieved from
the parameter symbols.
by bringing homogenization of # $Apply projections back.
Seems to be a hk-type inference issue. Needs further investigation but
is not high priority right now.
@odersky
Copy link
Contributor Author

odersky commented Dec 6, 2015

Rebased to master

*
* (2) Try to eta expand the constructor of `other`.
*
* (3a) In mode `TypeVarsMissConetxt` replace the projection's hk constructor parameter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: TypevarsMissContext

@smarter
Copy link
Member

smarter commented Dec 6, 2015

The following:

object Test {
  def foo[M[X] <: List[X]](x: M[Int]) = ???
}

gets pretty-printed after frontend as:

package <empty> {
  final lazy module val Test: Test$ = new Test$()
  final module class Test$() extends Object() { this: Test.type => 
    def foo[M <: [] -> <: scala.collection.immutable.List[X0]](x: M[Int]): Nothing = ???
  }
}

The list of type lambda arguments is [] but should be [X0]

@odersky odersky mentioned this pull request Dec 7, 2015
As remarked by @smarter, argInfos does not work for type lambdas,
so argBoundss is always Nil.
@odersky
Copy link
Contributor Author

odersky commented Dec 11, 2015

@smarter The print problem should be fixed with 1c77b03.

@odersky
Copy link
Contributor Author

odersky commented Dec 11, 2015

All comments should be addressed now.

@smarter
Copy link
Member

smarter commented Dec 11, 2015

I'm looking into why t3152.scala stopped compiling, I'd like to fix this before merging this PR.

@smarter
Copy link
Member

smarter commented Dec 11, 2015

adaptIfHK is wrong, it bypasses variance checks and allows this to compile:

class HKCov[M[+_]] {
  def upcast(m: M[Int]): M[Any] = m
}
class Foo[T]
object Test {
  val x: HKCov[Foo] = new HKCov[Foo]
  val fi: Foo[Int] = new Foo[Int]
  val fa: Foo[Any] = x.upcast(fi)
}

The type parameter of Foo is invariant so it shouldn't be possible to pass Foo to HKCov, however adaptIfHK rewrites [X] => Foo[X] into [+X] => Foo[X], this opens a soudness hole.

I've tried simply removing adaptIfHK and nothing seems to break, and even better: tests/pending/pos/t3152.scala now successfully compiles!

Do you have a test case where adaptIfHK is actually needed?

@odersky
Copy link
Contributor Author

odersky commented Dec 11, 2015

The comment to adaptIfHK gives some clue. It certainly was needed at some point for compileStdLib. To make sure, it would be good to just compile with some of the mutable classes mentioned in the comment. I.e. starting with GenTraversable and ListBuffer and then add a few.

@odersky
Copy link
Contributor Author

odersky commented Dec 11, 2015

Indeed we need to test whether the variances correspond before doing the adaptation. I.e. if the context requires nonvariant but the argument is covariant OK, in the other direction not.

Previously adaptIfHK was performed on every type application. This made
t3152 fail. We now do this only on demand, in isSubType. t3152 now passes
again. But the change unmasked another error, which makes Iter2 fail to compile.
Comment explains why following aliases in general is incomplete and potentially unsound.
This makes Iter2 compile, but causes cyclic reference errors for pos/sets.scala.
The tightened subtyping algorithm led to a cycle in baseTypeRef when
compiling sets.scala. This commit fixes the problem.
Any is a supertype of every other type, so no need to analyze types in detail.
This also fixes the cyclic reference error observed for sets.scala, but only
for the special case where the base class is Any.
The change in subtyping led to a deep subtype recursion for sets.scala.
It seems legit, so the -Yno-deep-subtypes check is disabled.
@odersky odersky merged commit 8a9e89a into scala:master Dec 15, 2015
@allanrenucci allanrenucci deleted the change-typeapply branch December 14, 2017 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants