Dotty: Interaction between multiversal equality and incremental compilation

Created on 31 May 2020  路  2Comments  路  Source: lampepfl/dotty

Minimized code

Initial this code is okay and compiled as it should
Then after changing the Currency.scala to define an Eql of EUR or CHF this code will not compile.
The problem is the incremental compilation will not recompile this compilation unit. Only if the two compilation units are on different compilation-times/modules

File src/main/scala/Currency.scala

sealed trait Currency
object Currency {
  object EUR extends Currency
  object CHF extends Currency
}

File src/test/scala/Demo.scala

import Currency._
object Demo extends App {
  println(EUR == CHF)
}

Compile and run Demo (all ok)
Then change File src/main/scala/Currency.scala to:

sealed trait Currency
object Currency {
  object EUR extends Currency { given Eql[EUR.type, EUR.type] = Eql.derived }
  object CHF extends Currency { given Eql[CHF.type, CHF.type] = Eql.derived }
}

I also create a branch with the minimal amount of code: https://github.com/FabioPinheiro/cats-money/tree/dotty-MultiversalEquality_IncrementalCompilation/src

Output

If we try to compile and run Demo after the change everything seems okay.
But it shouldn't be. The Demo.scala is never recompiled

Expectation

If we try to clean compile it gives this error:

[error] 5 |  println(EUR == CHF)
[error]   |          ^^^^^^^^^^
[error]   |Values of types object Currency.EUR and object Currency.CHF cannot be compared with == or !=
[error] one error found
[error] (Test / compileIncremental) Compilation failed
bug

Most helpful comment

Hi @FabioPinheiro

This ticket does not seem very urgent. Do you think it can be a good first ticket?

This is probably not a great first ticket because the solution is not clear cut. The issue is that during typechecking we look for an instance of Eql to decide whether the values can be compared, but we don't actually keep that instance in the AST, because the == method does not require it. This is problematic because incremental compilation works using a compiler phase (called ExtractDependencies) which traverse the AST to find all the dependencies. I can see two ways of fixing it:

  • Somehow store in the AST all the Eql instances we looked for as part of strict equality checks, this is doable but maybe a bit hacky.
  • If we could record dependencies "on the fly" as we see them, then we could immediately record the dependency on the Eql instance without storing anything. This is something that @bishabosha might work on as part of his work on incremental compilation, so I'm tentatively assigning this issue to him.

It would be amazing if I managed to contribute to the dotty compiler. Even if it's just a small thing.

I'm sure we can find stuff for you to work on! A good one might be helping advance the support for scala.js in dotty since we have a whole guide on how to do that: https://gist.github.com/sjrd/e0823a5bddbcef43999cdaa032b1220c. Otherwise, have a look at issues and/or come to https://gitter.im/lampepfl/dotty and we'll try to find something for you.

All 2 comments

Hey @smarter
This ticket does not seem very urgent. Do you think it can be a good first ticket? If so, could you point me in the right direction?
I discovered this Thursday that I will have a lot of free time next month.
So I want to use my free time to play with projects that I love and to make some more open source contributions.
It would be amazing if I managed to contribute to the dotty compiler. Even if it's just a small thing.

Hi @FabioPinheiro

This ticket does not seem very urgent. Do you think it can be a good first ticket?

This is probably not a great first ticket because the solution is not clear cut. The issue is that during typechecking we look for an instance of Eql to decide whether the values can be compared, but we don't actually keep that instance in the AST, because the == method does not require it. This is problematic because incremental compilation works using a compiler phase (called ExtractDependencies) which traverse the AST to find all the dependencies. I can see two ways of fixing it:

  • Somehow store in the AST all the Eql instances we looked for as part of strict equality checks, this is doable but maybe a bit hacky.
  • If we could record dependencies "on the fly" as we see them, then we could immediately record the dependency on the Eql instance without storing anything. This is something that @bishabosha might work on as part of his work on incremental compilation, so I'm tentatively assigning this issue to him.

It would be amazing if I managed to contribute to the dotty compiler. Even if it's just a small thing.

I'm sure we can find stuff for you to work on! A good one might be helping advance the support for scala.js in dotty since we have a whole guide on how to do that: https://gist.github.com/sjrd/e0823a5bddbcef43999cdaa032b1220c. Otherwise, have a look at issues and/or come to https://gitter.im/lampepfl/dotty and we'll try to find something for you.

Was this page helpful?
0 / 5 - 0 ratings