Strange type inference involving "with" when code is used from a library
reproduction steps
using Scala (2.12.11, 2.13.4),
The following code defined inside a library:
trait OtherType
class Foo {
def bar[T](t: T): T with OtherType = ???
}
The following code in an application using the library:
val g1: Int with OtherType = new Foo().bar(5)
val g2: Int with OtherType = new Foo().bar[Int](5)
problem
g1 does not compile. It has the error:
[error] found : Int(5)
[error] required: OtherType with Int
g2 compiles just fine.
However - if Foo is defined inside the same application as g1 and g2, they both compile.
I would expect both g1 and g2 to compile whether Foo comes from a library or application code.
Dale and I took a quick look at this. Either the pickle is wrong, or the pickle is right but is unpickled incorrectly, or... something truly weird is happening.
So if someone wants to look into this, those are the hypotheses to pursue, in order.
Not sure whether to "help wanted" this one. On the one hand, the minimization is small and doesn't involve obscure language features, so that makes it feel like we ought to fix it. On the other hand, presumably it's been broken forever and nobody noticed.
I find it very surprising. As far as I'm aware, our use-case is exactly the same as shapeless' @@ tags, which boil down to an alias of with. I think I remember reproducing this issue with shapeless tags too but not 100% sure.
This bug really limits the abstraction you can do over with and @@, I'd be surprised if no one has ever noticed before. But clearly no one has ever reported it!
Let's "help wanted" it since it would definitely be great if a volunteer at least dug into it far enough that we understand what's going on better inside the compiler here. Then we'd have some idea of whether it's an easy fix or not.
Let's "help wanted" it since it would definitely be great if a volunteer at least dug into it far enough that we understand what's going on better inside the compiler here. Then we'd have some idea of whether it's an easy fix or not.
I'm interested in this, but don't know how to fix it. This is the second similar problem I've seen recently (and one I forgot.)
Strangely enough, I also reproduced it in sandbox mode, val g1: Int with OtherType = new Foo().bar(5) and got the wrong type when folding the constants, ending up with val g1: Int with OtherType = new Foo().bar[T](5). https://github.com/scala/scala/blob/3faf9a98282a2f06219fd0b05b7fede2ab8fb326/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L3822
My test:
val g1: Int with OtherType = new Foo().bar(5) // tpe check failed, : Int <:< Int with OtherType => it's false
val g2: Int with OtherType = new Foo().bar[Int](5) // tpe check passed : Int <:< Int
val g3 = new Foo().bar(5) // tpe check passed : Int <:< ?
val g4 = new Foo().bar[Int](5) // tpe check passed : Int <:< ?
For ConstantType, is it feasible to judge only one of the parents of the RefinedType by <:<?