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

java.lang.UnsupportedOperationException: Position.point on NoPosition in chimney 0.8.0 #411

Closed
mariussoutier opened this issue Oct 19, 2023 · 17 comments · Fixed by #476
Closed
Labels
bug in compiler Possible compiler bug, either library can work around it or it's a wontfix bug Erroneous behavior in existing features

Comments

@mariussoutier
Copy link

Hi there,

my codebase was working fine with Chimney 0.7.x, but now I'm hitting a serious compilation exception: java.lang.UnsupportedOperationException: Position.point on NoPosition.

Unfortunately there's no hint where this might happen. We're using transformInto, into.withXYZ.transform, using.ignoreRedundantPatcherFields.patch all over the place, sometimes even wrapped.

Full stack trace:

[error] ## Exception when compiling 46 sources to [...]/target/scala-2.13/classes
[error] java.lang.UnsupportedOperationException: Position.point on NoPosition
[error] scala.reflect.internal.util.Position.fail(Position.scala:24)
[error] scala.reflect.internal.util.UndefinedPosition.point(Position.scala:102)
[error] scala.reflect.internal.util.UndefinedPosition.point(Position.scala:97)
[error] scala.tools.nsc.typechecker.TypeDiagnostics$UnusedPrivates.sympos(TypeDiagnostics.scala:646)
[error] scala.tools.nsc.typechecker.TypeDiagnostics$UnusedPrivates.$anonfun$unusedParams$2(TypeDiagnostics.scala:665)
[error] scala.tools.nsc.typechecker.TypeDiagnostics$UnusedPrivates.$anonfun$unusedParams$2$adapted(TypeDiagnostics.scala:665)
[error] scala.math.Ordering$$anon$1.compare(Ordering.scala:141)
[error] java.base/java.util.TimSort.binarySort(TimSort.java:296)
[error] java.base/java.util.TimSort.sort(TimSort.java:239)
[error] java.base/java.util.Arrays.sort(Arrays.java:1233)
[error] scala.collection.SeqOps.sorted(Seq.scala:728)
[error] scala.collection.SeqOps.sorted$(Seq.scala:719)
[error] scala.collection.immutable.List.scala$collection$immutable$StrictOptimizedSeqOps$$super$sorted(List.scala:79)
[error] scala.collection.immutable.StrictOptimizedSeqOps.sorted(StrictOptimizedSeqOps.scala:78)
[error] scala.collection.immutable.StrictOptimizedSeqOps.sorted$(StrictOptimizedSeqOps.scala:78)
[error] scala.collection.immutable.List.sorted(List.scala:79)
[error] scala.collection.SeqOps.sortBy(Seq.scala:783)
[error] scala.collection.SeqOps.sortBy$(Seq.scala:783)
[error] scala.collection.AbstractSeq.sortBy(Seq.scala:1190)
[error] scala.tools.nsc.typechecker.TypeDiagnostics$UnusedPrivates.unusedParams(TypeDiagnostics.scala:665)
[error] scala.tools.nsc.typechecker.TypeDiagnostics$checkUnused.run(TypeDiagnostics.scala:771)
[error] scala.tools.nsc.typechecker.TypeDiagnostics$checkUnused.apply(TypeDiagnostics.scala:788)
[error] scala.tools.nsc.typechecker.Analyzer$typerFactory$TyperPhase.apply(Analyzer.scala:136)
[error] scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:480)
[error] scala.tools.nsc.typechecker.Analyzer$typerFactory$TyperPhase.run(Analyzer.scala:111)
[error] scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1546)
[error] scala.tools.nsc.Global$Run.compileUnits(Global.scala:1530)
[error] scala.tools.nsc.Global$Run.compileSources(Global.scala:1522)
[error] scala.tools.nsc.Global$Run.compileFiles(Global.scala:1635)
[error] scala.tools.xsbt.CachedCompiler0.run(CompilerBridge.scala:176)
[error] scala.tools.xsbt.CachedCompiler0.run(CompilerBridge.scala:139)
[error] scala.tools.xsbt.CompilerBridge.run(CompilerBridge.scala:43)
[error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:91)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:193)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:248)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:183)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:163)
[error] sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:239)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:163)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:211)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:534)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:534)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5(Incremental.scala:180)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5$adapted(Incremental.scala:178)
[error] sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:464)
[error] sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:116)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52)
[error] sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:263)
[error] sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:419)
[error] sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:506)
[error] sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:406)
[error] sbt.internal.inc.Incremental$.apply(Incremental.scala:172)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:534)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:488)
[error] sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:425)
[error] sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137)
[error] sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:2371)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$2(Defaults.scala:2321)
[error] sbt.internal.server.BspCompileTask$.$anonfun$compute$1(BspCompileTask.scala:31)
[error] sbt.internal.io.Retry$.apply(Retry.scala:47)
[error] sbt.internal.io.Retry$.apply(Retry.scala:29)
[error] sbt.internal.io.Retry$.apply(Retry.scala:24)
[error] sbt.internal.server.BspCompileTask$.compute(BspCompileTask.scala:31)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:2319)
[error] scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:63)
[error] sbt.std.Transform$$anon$4.work(Transform.scala:69)
[error] sbt.Execute.$anonfun$submit$2(Execute.scala:283)
[error] sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:24)
[error] sbt.Execute.work(Execute.scala:292)
[error] sbt.Execute.$anonfun$submit$1(Execute.scala:283)
[error] sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] sbt.CompletionService$$anon$2.call(CompletionService.scala:65)
[error] java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
[error] java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[error] java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[error] java.base/java.lang.Thread.run(Thread.java:833)
[error]

Since the stack trace might not be very helpful, can you give me a hint in what kind of construct this might be occurring? We're making extensive use of Chimney so this is kind of tedious to debug.

@mariussoutier mariussoutier added the bug Erroneous behavior in existing features label Oct 19, 2023
@mariussoutier
Copy link
Author

mariussoutier commented Oct 19, 2023

a.patchUsing(b) seems to be the culprit. a.using(b).patch is working fine.

@MateuszKubuszok
Copy link
Member

MateuszKubuszok commented Oct 19, 2023

Hey, thanks for the ticket!

I would need:

  • Scala version
  • some small reproduction

I don't see our macros in the stack trace, so I can only guess there is a bug in the compiler which we haven't triggered before and are triggering now(?). When I google NoPosition I see issues like scalameta/scalameta#1183 but the only position we are using is c.enclosingPosition, so I cannot tell anything more without any reproduction.

It doesn't have to be super minimized or using only Chimney, just remove all NDA-company-specific details.

Alternatively I found a similar ticker for scala/bug#10604. I am not sure if it is still relevant but you might try increasing the stack size and see if that's an issue with hidden StackOverflow inside a compiler.

@mariussoutier
Copy link
Author

mariussoutier commented Oct 19, 2023

Scala version is 2.13.12.

@mariussoutier
Copy link
Author

mariussoutier commented Oct 19, 2023

I was able to pinpoint the error to an interaction with Circe, specifically if there is a configured codec implicit val codec: Codec[Event] = io.circe.generic.extras.semiauto.deriveConfiguredCodec available for the class that is either patcher or patchee. io.circe.generic.semiauto.deriveCodec is working fine.

@mariussoutier
Copy link
Author

mariussoutier commented Oct 19, 2023

import io.circe.Codec
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredCodec
import io.circe.generic.semiauto.deriveCodec
import io.scalaland.chimney.dsl._

object ChimneyBug {
  private def handleEvent(state: State, event: Event) =
    (state, event) match {
      case (active: State.Active, updated: Event.A) =>
        //  Working: active.using(updated).patch
        active.patchUsing(updated)
    }

  sealed trait Event
  object Event {
    case class A(
                  a: String,
                ) extends Event

    implicit val configuration = Configuration.default.withDiscriminator("class").withDefaults
    implicit val codec: Codec[Event] = deriveConfiguredCodec
    // Working: implicit val codec: Codec[Event] = deriveCodec
  }
  
  sealed trait State
  object State {
    case class Active(
                       a: String,
                     ) extends State

    implicit val configuration = Configuration.default.withDiscriminator("class").withDefaults
    implicit val codec: Codec[State] = deriveConfiguredCodec
    // Working: implicit val codec: Codec[Event] = deriveCodec
  }
}

@MateuszKubuszok
Copy link
Member

MateuszKubuszok commented Oct 19, 2023

When I am testing your code in Scastie it compiles. Could you check if setting e.g. -Xss8m for Java options changes anything? It only needs to be changed for compilation, not for the deployment.

@mariussoutier
Copy link
Author

We're already at -J-Xss64m in our .sbtopts files.

@mariussoutier
Copy link
Author

mariussoutier commented Oct 20, 2023

But indeed the Scastie is working fine 😕

@mariussoutier
Copy link
Author

mariussoutier commented Oct 20, 2023

The issue seems to be with the compiler setting -Wmacros:both ("Lints code before and after applying a macro").

As soon as I disable this setting, the code compiles.

@MateuszKubuszok
Copy link
Member

MateuszKubuszok commented Oct 20, 2023

Unfortunatelly, I still cannot reproduce. I created this Scala CLI snippet, but it runs without issues.

//> using scala 2.13.12
//> using options -Wmacros:both -verbose -Xlog-implicits
//> using dep io.scalaland::chimney::0.8.0
//> using dep io.circe::circe-generic::0.14.6
//> using dep io.circe::circe-generic-extras::0.14.3

import io.circe.Codec
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredCodec
import io.circe.generic.semiauto.deriveCodec
import io.scalaland.chimney.dsl._

object ChimneyBug {
  private def handleEvent(state: State, event: Event) =
    (state, event) match {
      case (active: State.Active, updated: Event.A) =>
        //  Working: active.using(updated).patch
        active.patchUsing(updated)
    }

  sealed trait Event
  object Event {
    case class A(
                  a: String,
                ) extends Event

    implicit val configuration = Configuration.default.withDiscriminator("class").withDefaults
    implicit val codec: Codec[Event] = deriveConfiguredCodec
    // Working: implicit val codec: Codec[Event] = deriveCodec
  }

  sealed trait State
  object State {
    case class Active(
                       a: String,
                     ) extends State

    implicit val configuration = Configuration.default.withDiscriminator("class").withDefaults
    implicit val codec: Codec[State] = deriveConfiguredCodec
    // Working: implicit val codec: Codec[Event] = deriveCodec
  }

  def test = handleEvent(ChimneyBug.State.Active("A"), ChimneyBug.Event.A("B"))
}

object Main {
  def main(args: Array[String]): Unit =
    println(ChimneyBug.test)
}
scala-cli run .
Compiling project (Scala 2.13.12, JVM)
[a lot of verbose logs]
Compiled project (Scala 2.13.12, JVM)
Active(B)

There must be something more to your setup which produces the error. Do you use the newest sbt, are you using Windows?

@mariussoutier
Copy link
Author

Please also add the option "-Xlint:unused".

@mariussoutier
Copy link
Author

mariussoutier commented Oct 20, 2023

Alternatively -Wunused:explicits, -Wunused:params, -Wunused:linted, or -Wunused:implicits.

Any of them in combination with -Wmacros:both trigger the error.

@som-snytt
Copy link

I commented on the Scala ticket that it is failing just sorting warnings by position: probably it's not defensive about unpositioned trees produced by the macro. In that case, the workaround is not to lint it with -Wmacros:both. I'll try to confirm that and provide a fix, since sort order should not be fatal.

@mariussoutier
Copy link
Author

Thanks!

@codesurf42
Copy link

I have seen these errors quite often recently in my code base (using upgraded to 0.8.0 chimney for conversions to scalapb-generated hierarchy), usually appearing at some point when adding more and more of data structures. The only pattern I have found was related to missing internal conversions in the ADT for chimney, however instead of expected macro compile error for missing transformations, it was bluntly reported by NoPosition.
We don't use macros:both.
Scala 2.13.9 and 2.13.12
If I find it again, I can try to extract it.

@MateuszKubuszok
Copy link
Member

MateuszKubuszok commented Oct 27, 2023

@codesurf42 if it's not macro:both check if it also isn't (lack of) -Xss flag.

@MateuszKubuszok
Copy link
Member

Since this issue seem to be related to a compiler's bug, I'll close it for now. When the fix is released I'll add the information about it to the documentation.

@MateuszKubuszok MateuszKubuszok added the bug in compiler Possible compiler bug, either library can work around it or it's a wontfix label Apr 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug in compiler Possible compiler bug, either library can work around it or it's a wontfix bug Erroneous behavior in existing features
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants