Skip to content

Fix #7969: Don't let Typevars be bounded by ExprTypes #7985

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 2 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,17 @@ trait ConstraintHandling[AbstractContext] {
case inst =>
prune(inst)
}
case bound: ExprType =>
// ExprTypes are not value types, so type parameters should not
// be instantiated to ExprTypes. A scenario where such an attempted
// instantiation can happen is if we unify (=> T) => () with A => ()
// where A is a TypeParamRef. See the comment on EtaExpansion.etaExpand
// why types such as (=> T) => () can be constructed and i7969.scala
// as a test where this happens.
// Note that scalac by contrast allows such instantiations. But letting
// type variables be ExprTypes has its own problems (e.g. you can't write
// the resulting types down) and is largely unknown terrain.
NoType
case _ =>
pruneLambdaParams(bound)
}
Expand Down
13 changes: 13 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,19 @@ object EtaExpansion extends LiftImpure {
* In each case, the result is an untyped tree, with `es` and `expr` as typed splices.
*
* F[V](x) ==> (x => F[X])
*
* Note: We allow eta expanding a method with a call by name parameter like
*
* def m(x: => T): T
*
* to a value of type (=> T) => T. This type cannot be written in source, since
* by-name types => T are not legal argument types.
*
* It would be simpler to not allow to eta expand by-name methods. That was the rule
* initially, but at some point, the rule was dropped. Enforcing the restriction again
* now would break existing code. Allowing by-name parameters in function types seems to
* be OK. After elimByName they are all converted to regular function types anyway.
* But see comment on the `ExprType` case in function `prune` in class `ConstraintHandling`.
*/
def etaExpand(tree: Tree, mt: MethodType, xarity: Int)(implicit ctx: Context): untpd.Tree = {
import untpd._
Expand Down
5 changes: 5 additions & 0 deletions tests/neg/i7969.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object O{
def f(i: => Int): Int = 1
def m[A](a: A => Int) = 2
def n = m(f) // error: cannot eta expand
}