Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler runs out of memory when using -Ysafe-init-global #18628

Closed
q-ata opened this issue Sep 30, 2023 · 3 comments
Closed

Compiler runs out of memory when using -Ysafe-init-global #18628

q-ata opened this issue Sep 30, 2023 · 3 comments

Comments

@q-ata
Copy link
Contributor

q-ata commented Sep 30, 2023

Compiler version

3.4.0-RC1-bin-SNAPSHOT-git-48a7871 (commit 48a7871)

Details

The compiler runs out of memory when compiling the community project scalaParserCombinators with the -Ysafe-init-global flag enabled.

The stack trace is as follows:

[error] java.lang.OutOfMemoryError: Java heap space
[error] scala.collection.immutable.Map$EmptyMap$.updated(Map.scala:250)
[error] scala.collection.immutable.Map$EmptyMap$.updated(Map.scala:239)
[error] scala.collection.immutable.MapBuilderImpl.addOne(Map.scala:685)
[error] scala.collection.immutable.MapBuilderImpl.addOne(Map.scala:703)
[error] scala.collection.immutable.MapBuilderImpl.addOne(Map.scala:661)
[error] scala.collection.mutable.Growable.addAll(Growable.scala:62)
[error] scala.collection.mutable.Growable.addAll$(Growable.scala:57)
[error] scala.collection.immutable.MapBuilderImpl.addAll(Map.scala:710)
[error] scala.collection.immutable.Map$.from(Map.scala:661)
[error] scala.collection.immutable.Map$.from(Map.scala:172)
[error] scala.collection.MapOps.map(Map.scala:299)
[error] scala.collection.MapOps.map$(Map.scala:299)
[error] scala.collection.AbstractMap.map(Map.scala:405)
[error] dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen(Objects.scala:345)
[error] dotty.tools.dotc.transform.init.Objects$.widen(Objects.scala:592)
[error] dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen$$anonfun$1(Objects.scala:345)
[error] dotty.tools.dotc.transform.init.Objects$Env$LocalEnv$$Lambda$8990/0x0000000842355840.apply(Unknown Source)
[error] scala.collection.Iterator$$anon$9.next(Iterator.scala:584)
[error] scala.collection.mutable.Growable.addAll(Growable.scala:62)
[error] scala.collection.mutable.Growable.addAll$(Growable.scala:57)
[error] scala.collection.immutable.MapBuilderImpl.addAll(Map.scala:710)
[error] scala.collection.immutable.Map$.from(Map.scala:661)
[error] scala.collection.immutable.Map$.from(Map.scala:172)
[error] scala.collection.MapOps.map(Map.scala:299)
[error] scala.collection.MapOps.map$(Map.scala:299)
[error] scala.collection.AbstractMap.map(Map.scala:405)
[error] dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen(Objects.scala:345)
[error] dotty.tools.dotc.transform.init.Objects$.widen(Objects.scala:592)
[error] dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen$$anonfun$1(Objects.scala:345)
[error] dotty.tools.dotc.transform.init.Objects$Env$LocalEnv$$Lambda$8990/0x0000000842355840.apply(Unknown Source)
[error] scala.collection.Iterator$$anon$9.next(Iterator.scala:584)
[error] scala.collection.mutable.Growable.addAll(Growable.scala:62)
[error]            
java.lang.OutOfMemoryError: Java heap space
	at scala.collection.immutable.Map$EmptyMap$.updated(Map.scala:250)
	at scala.collection.immutable.Map$EmptyMap$.updated(Map.scala:239)
	at scala.collection.immutable.MapBuilderImpl.addOne(Map.scala:685)
	at scala.collection.immutable.MapBuilderImpl.addOne(Map.scala:703)
	at scala.collection.immutable.MapBuilderImpl.addOne(Map.scala:661)
	at scala.collection.mutable.Growable.addAll(Growable.scala:62)
	at scala.collection.mutable.Growable.addAll$(Growable.scala:57)
	at scala.collection.immutable.MapBuilderImpl.addAll(Map.scala:710)
	at scala.collection.immutable.Map$.from(Map.scala:661)
	at scala.collection.immutable.Map$.from(Map.scala:172)
	at scala.collection.MapOps.map(Map.scala:299)
	at scala.collection.MapOps.map$(Map.scala:299)
	at scala.collection.AbstractMap.map(Map.scala:405)
	at dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen(Objects.scala:345)
	at dotty.tools.dotc.transform.init.Objects$.widen(Objects.scala:592)
	at dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen$$anonfun$1(Objects.scala:345)
	at dotty.tools.dotc.transform.init.Objects$Env$LocalEnv$$Lambda$8990/0x0000000842355840.apply(Unknown Source)
	at scala.collection.Iterator$$anon$9.next(Iterator.scala:584)
	at scala.collection.mutable.Growable.addAll(Growable.scala:62)
	at scala.collection.mutable.Growable.addAll$(Growable.scala:57)
	at scala.collection.immutable.MapBuilderImpl.addAll(Map.scala:710)
	at scala.collection.immutable.Map$.from(Map.scala:661)
	at scala.collection.immutable.Map$.from(Map.scala:172)
	at scala.collection.MapOps.map(Map.scala:299)
	at scala.collection.MapOps.map$(Map.scala:299)
	at scala.collection.AbstractMap.map(Map.scala:405)
	at dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen(Objects.scala:345)
	at dotty.tools.dotc.transform.init.Objects$.widen(Objects.scala:592)
	at dotty.tools.dotc.transform.init.Objects$Env$LocalEnv.widen$$anonfun$1(Objects.scala:345)
	at dotty.tools.dotc.transform.init.Objects$Env$LocalEnv$$Lambda$8990/0x0000000842355840.apply(Unknown Source)
	at scala.collection.Iterator$$anon$9.next(Iterator.scala:584)
	at scala.collection.mutable.Growable.addAll(Growable.scala:62)
[error] [launcher] error during sbt launcher: java.lang.OutOfMemoryError: Java heap space
@q-ata q-ata added itype:bug itype:crash stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 30, 2023
@liufengyun liufengyun self-assigned this Sep 30, 2023
@liufengyun liufengyun added area:initialization and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 30, 2023
@liufengyun
Copy link
Contributor

Here is a minimization without dependency:

abstract class Reader[+T] {
  def first: T

  def rest: Reader[T]

  def atEnd: Boolean
}

trait Parsers {
  type Elem
  type Input = Reader[Elem]

  sealed abstract class ParseResult[+T] {
    val successful: Boolean

    def map[U](f: T => U): ParseResult[U]

    def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U]
  }

  sealed abstract class NoSuccess(val msg: String) extends ParseResult[Nothing] { // when we don't care about the difference between Failure and Error
    val successful = false

    def map[U](f: Nothing => U) = this

    def flatMapWithNext[U](f: Nothing => Input => ParseResult[U]): ParseResult[U]
      = this
  }

  case class Failure(override val msg: String) extends NoSuccess(msg)

  case class Error(override val msg: String) extends NoSuccess(msg)

  case class Success[+T](result: T, val next: Input) extends ParseResult[T] {
    val successful = true

    def map[U](f: T => U) = Success(f(result), next)

    def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U] = f(result)(next) match {
      case s @ Success(result, rest) => Success(result, rest)
      case f: Failure => f
      case e: Error => e
    }
  }

  case class ~[+a, +b](_1: a, _2: b) {
    override def toString = s"(${_1}~${_2})"
  }

  abstract class Parser[+T] extends (Input => ParseResult[T]) {
    def apply(in: Input): ParseResult[T]

    def ~ [U](q: => Parser[U]): Parser[~[T, U]] = { lazy val p = q // lazy argument
      (for(a <- this; b <- p) yield new ~(a,b))
    }

    def flatMap[U](f: T => Parser[U]): Parser[U]
      = Parser{ in => this(in) flatMapWithNext(f)}

    def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))}
      = Parser{ in => this(in) map(f)}

    def ^^ [U](f: T => U): Parser[U] = map(f)
  }

  def Parser[T](f: Input => ParseResult[T]): Parser[T]
    = new Parser[T]{ def apply(in: Input) = f(in) }

  def accept(e: Elem): Parser[Elem] = acceptIf(_ == e)("'"+e+"' expected but " + _ + " found")

  def acceptIf(p: Elem => Boolean)(err: Elem => String): Parser[Elem] = Parser { in =>
    if (in.atEnd) Failure("end of input")
    else if (p(in.first)) Success(in.first, in.rest)
    else Failure(err(in.first))
  }
}


object grammars3 extends Parsers {
  type Elem = String

  val a: Parser[String] = accept("a")
  val b: Parser[String] = accept("b")

  val AnBnCn: Parser[List[String]] = {
    repMany(a,b)
  }

  def repMany[T](p: => Parser[T], q: => Parser[T]): Parser[List[T]] =
    p~repMany(p,q)~q ^^ {case x~xs~y => x::xs:::(y::Nil)}
}

@liufengyun
Copy link
Contributor

The following test inspired by the code above triggers the OOM exception as well:

object Test:
  class Box(val x: Int)

  def recur(a: => Box, b: => Box): Int =
    a.x + recur(a, b) + b.x

  recur(Box(1), Box(2))

@liufengyun liufengyun mentioned this issue Nov 3, 2023
liufengyun added a commit that referenced this issue Nov 9, 2023
This PR fixes the minimized test of #18628 that previously runs
infinitely on the global initialization checker.
@liufengyun
Copy link
Contributor

Fixed by #18841

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants