bug icon indicating copy to clipboard operation
bug copied to clipboard

Subtractable nightmare on array loops in 2.12

Open scabug opened this issue 8 years ago • 12 comments

I am constantly having things like:

[error] /home/antonkulaga/denigma/processors/main/src/main/scala/org/clulab/swirl2/Reader.scala:173: type arguments [?,Iterable[Any] with Int => Any with scala.collection.generic.Subtractable[_ >: (Int, Int, String) with Int, Iterable[Any] with Int => Any with scala.collection.generic.Subtractable[_ >: (Int, Int, String) with Int, Equals]]{def seq: Iterable[Any] with Int => Any}] do not conform to trait Subtractable's type parameter bounds [A,+Repr <: scala.collection.generic.Subtractable[A,Repr]]
[error]     for(modifier <- tokens.indices) {

(note the code is from https://github.com/antonkulaga/processors that I try to port to 2.12.1) with java array loops in Scala 2.12.1 (same code works well on Scala 2.11.8).

scabug avatar Jan 16 '17 18:01 scabug

Imported From: https://issues.scala-lang.org/browse/SI-10151?orig=1 Reporter: Anton Kulaga (antonkulaga) Affected Versions: 2.12.1

scabug avatar Jan 16 '17 18:01 scabug

@som-snytt said: Reducedly,

package badindices

import scala.collection.mutable
import scala.collection.mutable.{ArrayBuffer, ListBuffer}

case class DirectedGraph[A](a: A)

class Reader {
  class CoNLLToken(
    val word:String,
    val pos:String,
    val lemma:String,
    val dep:(Int, String), // head, label
    val pred:Int,
    val frameBits:Array[String]) {
    override def toString:String = word + "/" + pos + "/" + dep._1 + "/" + dep._2 + "/" + pred
  }

  def toDirectedGraph(tokens:Array[CoNLLToken]):DirectedGraph[String] = {
    val edges = new mutable.ListBuffer[(Int, Int, String)] // head, modifier, label
    val roots = new mutable.HashSet[Int]()
    for(modifier <- tokens.indices) {
      val head = tokens(modifier).dep._1
      if(head >= 0)
        edges += new Tuple3(head, modifier, tokens(modifier).dep._2)
      else
        roots += modifier
    }
    DirectedGraph[String]("hi")
  }
}

with the challenging inference

      scala.Predef.refArrayOps[Reader.this.CoNLLToken](tokens).indices.foreach[scala.collection.mutable.Iterable[_ >: (Int, Int, String) with Int] with scala.collection.AbstractIterable[Any] with scala.collection.mutable.Cloneable[scala.collection.mutable.Iterable[_ >: (Int, Int, String) with Int] with scala.collection.mutable.Cloneable[scala.collection.mutable.Iterable[_ >: (Int, Int, String) with Int] with scala.collection.mutable.Cloneable[Cloneable with Mutable with Equals] with Int => Any{def seq: Cloneable with Mutable with Equals}] with Int => Any] with scala.collection.mutable.Builder[(Int, Int, String) with Int,Iterable[Any] with Int => Any{def seq: Iterable[Any] with Int => Any}] with Int => Any with Serializable with scala.collection.generic.Shrinkable[(Int, Int, String) with Int] with scala.collection.generic.Subtractable[_ >: (Int, Int, String) with Int, Iterable[Any] with Int => Any with scala.collection.generic.Subtractable[_ >: (Int, Int, String) with Int, Iterable[Any] with Int => Any with scala.collection.generic.Subtractable[_ >: (Int, Int, String) with Int, Equals]]{def seq: Iterable[Any] with Int => Any}] with scala.collection.script.Scriptable[_ >: (Int, Int, String) with Int]](((modifier: Int) => {
        val head: Int = tokens.apply(modifier).dep._1;
        if (head.>=(0))
          edges.+=(new (Int, Int, String)(head, modifier, tokens.apply(modifier).dep._2))
        else
          roots.+=(modifier)
      }));

scabug avatar Jan 16 '17 21:01 scabug

@som-snytt said: The workaround is to add a unit value after the if/else and avoid the inference.

scabug avatar Jan 16 '17 21:01 scabug

Encountered this one today... pretty awkward.

stuhood avatar Jun 06 '17 18:06 stuhood

Here is another example of how to reproduce (note the example is a bit contrived as we reduced to remove unnecessary logic)

case class Country(name: String)

object Countries {
  def find(name: String): Option[Country] = None
}

import scala.collection.mutable

object Main extends App {

  val data: Seq[(String, String)] = Nil

  val invalid = mutable.Set[String]()
  val countries = mutable.ListBuffer[Country]()

  data.foreach { case (label, code) =>
    Countries.find(code) match {
      case None => invalid
      case Some(c) => countries
    }
  }

}

sbt compile results in:

[error] /web/foo/Main.scala:16: type arguments [?,Iterable[java.io.Serializable] with String with Int => Any with scala.collection.generic.Subtractable[_ >: String with Country <: java.io.Serializable, Iterable[java.io.Serializable] with String with Int => Any with scala.collection.generic.Subtractable[_ >: String with Country <: java.io.Serializable, Equals]]{def seq: Iterable[java.io.Serializable] with String with Int => Any}] do not conform to trait Subtractable's type parameter bounds [A,+Repr <: scala.collection.generic.Subtractable[A,Repr]]
[error]   data.foreach { case (label, code) =>
[error]        ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 5 s, completed Jul 27, 2017 4:06:22 PM

mbryzek avatar Jul 27 '17 15:07 mbryzek

https://github.com/scala/bug/issues/10359 has a nice short reproduction (of what at least seems to be the same issue, investigation would be needed to confirm)

SethTisue avatar Mar 12 '18 18:03 SethTisue

I'm putting this on the 2.13.0-M4 milestone because I think we should at least check whether any of these reproducers still fail after new collections land. (If they stop failing, it won't mean the real inference issue is fixed, but it will lower the significance of the bug.)

SethTisue avatar Mar 12 '18 18:03 SethTisue

There are other type inference issues related to F-bounded types (I assume this is the case here) like #3528. The problem is in glb/lub of such types.

joroKr21 avatar Mar 12 '18 19:03 joroKr21

I’ve tried compiling the code of https://github.com/scala/bug/issues/10151#issuecomment-318390443 in 2.13.x branch and there is no error anymore (note that we have removed Subtractable in the new collections)

julienrf avatar Jun 22 '18 15:06 julienrf

Can someone suggest a more informative title for this ticket?

SethTisue avatar Jun 29 '18 13:06 SethTisue

I've created a gist displaying what I believe is the same bug but with a workaround that is slightly different than the samples shown above: https://gist.github.com/nivekastoreth/5c0e005c986a3827aa29a17a9274fb40

Because these are specs2 tests and not some unit loop, the workaround mentioned previously in this ticket wasn't applicable.

nivekastoreth avatar Jun 13 '19 18:06 nivekastoreth