Skip to content

StackOverflow when wrapping F-Bound type #11078

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

Closed
Katrix opened this issue Jan 12, 2021 · 3 comments · Fixed by #11192
Closed

StackOverflow when wrapping F-Bound type #11078

Katrix opened this issue Jan 12, 2021 · 3 comments · Fixed by #11192
Assignees
Milestone

Comments

@Katrix
Copy link
Contributor

Katrix commented Jan 12, 2021

Minimized code

trait Foo[A <: Foo[A]]
trait FooCreator[A <: Foo[A]] {
  def createFoo(): A
}

trait FooWrapper {
  type A <: Foo[A]
  def foo: A
}
object FooWrapper {
  def apply[A0 <: Foo[A0]](toWrap: A0): FooWrapper { type A = A0 } = new FooWrapper {
    type A = A0
    def foo: A0 = toWrap
  }
}

trait FooCreatorWrapper {
  type A <: Foo[A]
  def fooCreator: FooCreator[A]
}

sealed trait Bar
object Bar {
  case class Baz(wrapper: FooCreatorWrapper) extends Bar
}

def process(bar: Bar): FooWrapper = bar match {
  case Bar.Baz(wrapper) => FooWrapper(wrapper.fooCreator.createFoo())
}

Stuff which does not produce the error. No match, no creator, breaking out the expression into two lines with a val inbetween.

Output (click arrow to expand)

[error] java.lang.StackOverflowError
[error] dotty.tools.dotc.core.Types$NamedType.denot(Types.scala:2085)
[error] dotty.tools.dotc.core.TypeApplications$.safeDealias$extension(TypeApplications.scala:271)
[error] dotty.tools.dotc.core.TypeApplications$.appliedTo$extension(TypeApplications.scala:311)
[error] dotty.tools.dotc.core.Types$AppliedType.derivedAppliedType(Types.scala:4074)
[error] dotty.tools.dotc.core.Types$ApproximatingTypeMap.derivedAppliedType(Types.scala:5439)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver(Types.scala:5120)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:442)
[error] dotty.tools.dotc.core.Types$ApproximatingTypeMap.reapply(Types.scala:5492)
[error] dotty.tools.dotc.core.Types$ApproximatingTypeMap.expandBounds(Types.scala:5293)
[error] dotty.tools.dotc.core.Types$ApproximatingTypeMap.tryWiden(Types.scala:5309)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.derivedSelect(TypeOps.scala:457)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver(Types.scala:5117)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:442)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver$$anonfun$1(Types.scala:5167)
[error] dotty.tools.dotc.core.Types$LazyRef$.apply$$anonfun$1(Types.scala:2735)
[error] dotty.tools.dotc.core.Types$LazyRef.ref(Types.scala:2748)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver$$anonfun$1(Types.scala:5166)
[error] dotty.tools.dotc.core.Types$LazyRef$.apply$$anonfun$1(Types.scala:2735)
[error] dotty.tools.dotc.core.Types$LazyRef.ref(Types.scala:2748)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver$$anonfun$1(Types.scala:5166)
[error] dotty.tools.dotc.core.Types$LazyRef$.apply$$anonfun$1(Types.scala:2735)
[error] dotty.tools.dotc.core.Types$LazyRef.ref(Types.scala:2748)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldOver(Types.scala:5605)
[error] dotty.tools.dotc.core.Types$NamedPartsAccumulator.apply(Types.scala:5661)
[error] dotty.tools.dotc.core.Types$NamedPartsAccumulator.apply(Types.scala:5639)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.op$proxy19$1(Types.scala:5535)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldArgs$1(Types.scala:5535)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldOver(Types.scala:5539)
[error] dotty.tools.dotc.core.Types$NamedPartsAccumulator.apply(Types.scala:5653)
[error] dotty.tools.dotc.core.Types$NamedPartsAccumulator.apply(Types.scala:5639)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldOver(Types.scala:5605)
[error] dotty.tools.dotc.core.Types$NamedPartsAccumulator.apply(Types.scala:5661)
[error] dotty.tools.dotc.core.Types$NamedPartsAccumulator.apply(Types.scala:5639)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.op$proxy19$1(Types.scala:5535)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldArgs$1(Types.scala:5535)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldOver(Types.scala:5539)
...
@Katrix
Copy link
Contributor Author

Katrix commented Jan 12, 2021

Ran into this as well, using some of the same code. The stack trace is a bit different, so can make a new issue for it if it's not actually the same crash. The cause of the error is the type signature of doThing, if it's changed to FooWrapper, everything compiles.

trait Foo[A <: Foo[A]]
trait FooWrapper:
  self =>
  type A <: Foo[A]
  def doThing(foo: FooWrapper): FooWrapper { type A = self.A } = ???
end FooWrapper

val foos: scala.Seq[FooWrapper] = ???
val newFoo = foos.foldLeft(??? : FooWrapper)((topFoo, foo) => topFoo.doThing(foo))

Error:

[error] java.lang.StackOverflowError
[error] dotty.tools.dotc.core.Types$NamedType.denot(Types.scala:2085)
[error] dotty.tools.dotc.core.Types$NamedType.info(Types.scala:2077)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:417)
[error] dotty.tools.dotc.core.Types$TypeMap.op$proxy14$1(Types.scala:5110)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver(Types.scala:5110)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:442)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver$$anonfun$1(Types.scala:5167)
[error] dotty.tools.dotc.core.Types$LazyRef$.apply$$anonfun$1(Types.scala:2735)
[error] dotty.tools.dotc.core.Types$LazyRef.ref(Types.scala:2748)
[error] dotty.tools.dotc.core.Types$TypeMap.mapOver$$anonfun$1(Types.scala:5166)
[error] dotty.tools.dotc.core.Types$LazyRef$.apply$$anonfun$1(Types.scala:2735)
[error] dotty.tools.dotc.core.Types$LazyRef.ref(Types.scala:2748)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldOver(Types.scala:5605)
[error] dotty.tools.dotc.core.Types$TypeTraverser.traverseChildren(Types.scala:5622)
[error] dotty.tools.dotc.sbt.ExtractDependenciesCollector$TypeDependencyTraverser.traverse(ExtractDependencies.scala:468)
[error] dotty.tools.dotc.core.Types$TypeTraverser.apply(Types.scala:5621)
[error] dotty.tools.dotc.core.Types$TypeTraverser.apply(Types.scala:5621)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.op$proxy19$1(Types.scala:5535)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldArgs$1(Types.scala:5535)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldOver(Types.scala:5539)
[error] dotty.tools.dotc.core.Types$TypeTraverser.traverseChildren(Types.scala:5622)
[error] dotty.tools.dotc.sbt.ExtractDependenciesCollector$TypeDependencyTraverser.traverse(ExtractDependencies.scala:468)
[error] dotty.tools.dotc.core.Types$TypeTraverser.apply(Types.scala:5621)
[error] dotty.tools.dotc.core.Types$TypeTraverser.apply(Types.scala:5621)
[error] dotty.tools.dotc.core.Types$TypeAccumulator.foldOver(Types.scala:5605)
[error] dotty.tools.dotc.core.Types$TypeTraverser.traverseChildren(Types.scala:5622)
[error] dotty.tools.dotc.sbt.ExtractDependenciesCollector$TypeDependencyTraverser.traverse(ExtractDependencies.scala:468)

@Katrix
Copy link
Contributor Author

Katrix commented Jan 12, 2021

And another one. Don't think this is a crash, it just throws a really, REALLY large type back. Again, if I should make another issue, just say so. Too large for me to post here. Uses Foo and FooWrapper as defined earlier

def error(fooWrapper: FooWrapper, processor: [A <: Foo[A]] => A => A): FooWrapper =
  FooWrapper(processor(fooWrapper.foo))

liufengyun added a commit to dotty-staging/dotty that referenced this issue Jan 22, 2021
This avoids expanding F-Bounds as well.
liufengyun added a commit to dotty-staging/dotty that referenced this issue Jan 22, 2021
This avoids expanding F-Bounds as well.

Changes are needed to fix the following bootstrapping error:

``` Scala
[error] -- [E007] Type Mismatch Error: /Users/fliu/Documents/dotty/compiler/src/dotty/tools/dotc/typer/Typer.scala:3232:30
[error] 3232 |              Some((paramSyms(paramName), tree))
[error]      |                              ^^^^^^^^^
[error]      |        Found:    (paramName : dotty.tools.dotc.core.Names.TermName)
[error]      |        Required: dotty.tools.dotc.core.Symbols.Symbol#ThisName
```

It seems to me widening of the bound in the case above may cause
soundness issues: how do we know the symbols are all TermSymbols?
Semantically, we know `paramSymss` are all term symbols, but the
contract is not in types.
liufengyun added a commit to dotty-staging/dotty that referenced this issue Jan 22, 2021
odersky added a commit that referenced this issue Jan 27, 2021
Fix #11078: avoid widening F-bounds in type avoidance
@liufengyun
Copy link
Contributor

@Katrix Thanks for your report. We still need to fix the problem related to the following piece of code:

def error(fooWrapper: FooWrapper, processor: [A <: Foo[A]] => A => A): FooWrapper =
  FooWrapper(processor(fooWrapper.foo))

A workaround is to supply the type argument explicitly:

def error(fooWrapper: FooWrapper, processor: [A <: Foo[A]] => A => A): FooWrapper =
-  FooWrapper(processor(fooWrapper.foo))
+  FooWrapper[fooWrapper.A](processor(fooWrapper.foo))

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

Successfully merging a pull request may close this issue.

3 participants