5

Here is a simple example:

trait Proposition[T] {
  type Repr = T
}

trait Scope {

  type OUT

  type Consequent = Proposition[_ <: OUT]

  abstract class Proof[-I, +P <: Consequent] {
    final def instanceFor(v: I): P#Repr = ???
    final def apply(v: I): P#Repr = instanceFor(v)
  }
}

This gives the compilation error:


[Error] ....scala:44: type mismatch;
 found   : _$1(in type Consequent)
 required: (some other)_$1(in type Consequent)

Where does this (some other) come from? Is it a compiler bug caused by a clear rule of type selection (which should be theoretically solved in scala 3)?

UPDATE 1 Sorry I just realised that P#Repr should not be called type selection, which should only refers to val p: P;p.Repr, now it added even more confusion because:

  • I don't even know the name of this grammar, yet I kept using it for a long time

  • It is not even defined in DOT calculus. So scala 3 support is questionable

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
tribbloid
  • 4,026
  • 14
  • 64
  • 103
  • Not sure if this is a bug, but this is probably a consequence of type projections being too wide. – Luis Miguel Mejía Suárez Sep 26 '21 at 20:11
  • What does that mean? also type projection is not a DOT calculus grammar – tribbloid Sep 26 '21 at 20:20
  • That `P#Repr` is usually meaningless, that is why it was unsound and that is why it was removed. – Luis Miguel Mejía Suárez Sep 26 '21 at 20:25
  • Yeah, now I've found a long list of discussion regarding its soundness, so I'll just need to figure out a circumvention of it – tribbloid Sep 26 '21 at 20:29
  • @tribbloid I can't reproduce in 2.13.6 https://scastie.scala-lang.org/DmytroMitin/FfC8vI7fQjeaai5xLLfLiQ/1 What's your version of Scala? – Dmytro Mitin Sep 26 '21 at 20:31
  • @LuisMiguelMejíaSuárez Well, type projections are not so meaningless. They are one of two sorts of type-level calculations in Scala 2 (the other sort is type classes). In some sense match types replace type projections in this role in Scala 3 (although on value level match types work currently not so well). Type projections is a primary notion in specification of Scala 2 (I guess there is no spec of Scala 3 yet), for example path-dependent types etc. are defined via type projections. Unsoundness of type projections outside using along with intersection types and lower bounds is disputable. – Dmytro Mitin Sep 26 '21 at 20:38
  • @LuisMiguelMejíaSuárez Did you manage to reproduce? – Dmytro Mitin Sep 26 '21 at 20:38
  • @LuisMiguelMejíaSuárez And besides that type projections remain in Scala 3. Type projections on an abstract type are banned. – Dmytro Mitin Sep 26 '21 at 20:48
  • @DmytroMitin Sorry you are right, I simplify the example which seems to make the compiler easier to figure out. Let me modify it a bit. – tribbloid Sep 26 '21 at 20:57
  • 1
    Type projection as an extension called gDOT seems to be proven: https://github.com/lampepfl/dotty-feature-requests/issues/14. For the moment we still need a mechanical way to circumvent it using other features – tribbloid Sep 26 '21 at 21:00
  • @DmytroMitin you know I am always on mobile :) so no, I couldn't reproduce it. AFAIK _(but I don't know too much about it)_ path-dependent types and type projections are different things and the latter were planned to be removed from the language, but they manage to prove the soundness of a more simplified version of them; which again AFAIK doesn't cover this use case since `P#Repr` is a projection on an abstract type AFAIK, but I may be wrong. – Luis Miguel Mejía Suárez Sep 26 '21 at 21:05
  • 2
    I'm really sorry the example was now fixed. https://scastie.scala-lang.org/zxDRTVxFT3yZZMrUQy2akA – tribbloid Sep 26 '21 at 21:08
  • 1
    @LuisMiguelMejíaSuárez Path-dependent types and type projections are not completely different things because the latter are partial case of the former (at least in Scala 2). `p.Repr` is `p.type#Repr` by definition (according to the spec). So path-dependent types are defined in terms of type projections and singleton types. – Dmytro Mitin Sep 26 '21 at 21:20

1 Answers1

4

Looks like a bug.

I minimized your code till

trait Proposition[T] {
  type Repr = T
}

trait Scope {
  type Consequent = Proposition[_]

  abstract class Proof[P <: Consequent] {
    val instanceFor: P#Repr = ??? // doesn't compile
      // type mismatch;
      // found   : Proof.this.instanceFor.type (with underlying type _$1)
      // required: _$1
  }
}

https://scastie.scala-lang.org/DmytroMitin/DNRby7JGRc2TPZuwIM8ROA/1 (Scala 2.13.6)

So we can't even declare a single variable of type P#Repr.

It seems similar to bugs:


Where does this (some other) come from?

It comes from skolemization of an existential type

https://scala-lang.org/files/archive/spec/2.13/03-types.html#existential-types

https://en.wikipedia.org/wiki/Skolem_normal_form

Proposition[_] is a shorthand for Proposition[T] forSome { type T <: OUT }. If you replace Proposition[_] with the latter then the error message will be

type mismatch;
 found   : T(in type Consequent)
 required: (some other)T(in type Consequent)
      final def apply(v: I): P#Repr = instanceFor(v)
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Good to know, too bad we can't even verify if the problem is addressed by the latest compiler or not, until much later – tribbloid Sep 26 '21 at 22:36
  • Also, I didn't even use the existential type feature (which was also dropped in scala 3), are you referring to a more specific case? – tribbloid Sep 26 '21 at 22:48
  • Sorry your last part of the answer addressed the terminology. It is not dropped in scala 3, so ideally it should be given a new name – tribbloid Sep 26 '21 at 22:50
  • 1
    @tribbloid *"too bad we can't even verify if the problem is addressed by the latest compiler"* Actually we can. It's enough to [replace](https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala#L127) `if (!isConcrete(tp)) NotConcrete` with `if (!isConcrete(tp)) Realizable` (now we allow `P#Repr`) and such patched compiler compiles the code without errors (so it can't see other problems like `type mismatch`). – Dmytro Mitin Sep 26 '21 at 23:18
  • by "the latest" I mean scala 3.x – tribbloid Sep 27 '21 at 18:31
  • hmmm... so you did change on top of scala 3, why do they keep changing the syntax of the language? The last time I checked there is no type projection at all – tribbloid Sep 27 '21 at 19:08
  • I see what you are doing here .... you are overriding a core axiom of scala3's calculus! (the error message: P is not a legal path clearly indicates this) in this case I think it will be very hard to convince the maintainer to relax it. We may still need to wait for full acknowledgement of gDOT – tribbloid Sep 27 '21 at 19:51