bug
bug copied to clipboard
Nothing but frustration inferred
You probably would label this as an enhancement rather than a defect, but it bit me really hard in conjunction with #4377.
trait Cap
trait Op[C <: Cap] {
type Result
}
trait Exec[-C <: Cap, R]
trait ReadCap extends Cap
final class ReadOp[A] extends Op[ReadCap] {
type Result = A
}
def exec[C <: Cap, O <: Op[C]](op: O): Exec[C, O#Result] = null
exec(new ReadOp[Int])
/*
error: inferred type arguments [Nothing,this.ReadOp[Int]] do not conform to method exec's type parameter bounds [C <: this.Cap,O <: this.Op[C]]
exec(new ReadOp[Int])
^
*/
The first thing that comes to mind is to make Op's C a type member:
trait Cap
trait Op {
type C <: Cap
type Result
}
trait Exec[-C <: Cap, R]
trait ReadCap extends Cap
final class ReadOp[A] extends Op {
type C = ReadCap
type Result = A
}
def exec[O <: Op](op: O): Exec[O#C, O#Result] = null
exec(new ReadOp[Int])
Which works, until you need to bound Op#C (see #4377):
trait Ops { list =>
type C <: Cap
def seq: Seq[Op { type C >: list.C <: Cap }]
}
final class Ops1[O <: Op](op: O) extends Ops {
type C = O#C
def seq = Seq[O](op)
}
/*
error: type mismatch;
found : Seq[O]
required: Seq[this.Op{type C >: Ops1.this.C <: this.Cap}]
def seq = Seq[O](op)
^
*/
My best shot so far is to keep both type parameter and type member, use bounds-friendly [C <: Cap, O <: Op[C]] internally and expose inference-friendly [O <: Op[_ <: Cap]] to the users:
trait Cap
trait Op[C <: Cap] { op =>
final type CC = C
type Result
// Here goes horrid monster
final type Self[O >: this.type <: Op[_ <: Cap]] =
Op[O#CC] { type Result = op.Result }
final def self[O >: this.type <: Op[_ <: Cap]] =
this.asInstanceOf[Self[O]]
}
trait ReadCap extends Cap
final class ReadOp[A] extends Op[ReadCap] {
type Result = A
}
trait Ops[C <: Cap] {
def seq: Seq[Op[C1] forSome { type C1 >: C <: Cap }]
}
final class Ops1[C <: Cap, O <: Op[C]](op: O) extends Ops[C] {
def seq = Seq[O](op)
}
def inject[O <: Op[_ <: Cap]](op: O) =
new Ops1[O#CC, O#Self[O]](op.self[O])
inject(new ReadOp[Int])
Frustration achieved with 2.8.1 and 2.10.0.r24524-b20110321020039
Imported From: https://issues.scala-lang.org/browse/SI-4378?orig=1 Reporter: Mikhail Vorozhtsov (mikhail.vorozhtsov)
Mikhail Vorozhtsov (mikhail.vorozhtsov) said: Note that the naive
def inject[O <: Op[_ <: Cap]](op: O) =
new Ops1[O#CC, O](op)
does not typecheck.
Dotty infers C
def exec[C <: Cap, O <: Op[C]](op: O): Exec[C, op.Result] = null
def f = exec(new ReadOp[Int])
somebody copping Paul's issue naming style
I had the same thought! but technically, it should read, "Frustration, but Nothing inferred".