Skip to content

given instance is declared as erased, but is in fact used #13785

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
ghostdogpr opened this issue Oct 21, 2021 · 4 comments
Closed

given instance is declared as erased, but is in fact used #13785

ghostdogpr opened this issue Oct 21, 2021 · 4 comments
Labels
itype:bug stat:needs minimization Needs a self contained minimization

Comments

@ghostdogpr
Copy link
Contributor

Compiler version

3.1.0

Problem

This is a follow-up to #13044.

There are few occurrences where I observe the error given instance is declared as erased, but is in fact used, but increasing -Xmax-inlines doesn't solve the problem. Instead, the compilation goes on forever while using a lot of CPU.

To reproduce, clone this branch: https://github.com/ghostdogpr/caliban/tree/repro-1 (branch = repro-1)
In sbt: ++3.1.0 (the project cross-compiles and uses Scala 2 by default), then federation / compile.
You should get this:

[error] -- Error: /Users/pierre/GIT/caliban/federation/src/main/scala/caliban/federation/Federation.scala:103:66 
[error] 103 |    implicit val querySchema: Schema[R, Query] = genericSchema.gen[Query]
[error]     |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^
[error]     |         given instance gen is declared as erased, but is in fact used
[error]     | This location contains code that was inlined from SchemaDerivation.scala:29
[error]     | This location contains code that was inlined from SchemaDerivation.scala:115
[error]     | This location contains code that was inlined from SchemaDerivation.scala:228
[error]     | This location contains code that was inlined from SchemaDerivation.scala:29
[error]     | This location contains code that was inlined from SchemaDerivation.scala:115
[error]     | This location contains code that was inlined from SchemaDerivation.scala:228

If you add -Xmax-inlines: 50 to scala options, instead of the error it compiles forever with high CPU usage.

The code for the derivation is here: https://github.com/ghostdogpr/caliban/blob/repro-1/core/src/main/scala-3/caliban/schema/SchemaDerivation.scala
Uncommenting this line and commenting import genericSchema.gen instead removes the error.
Let me know if you need more details about it. Thanks!

@nicolasstucki
Copy link
Contributor

Seems like the library generates too much code while inlining. Up to -Xmax-inlines:43 it takes around 15 seconds to fail, then with -Xmax-inlines:44 it takes 70 seconds to fail and then it starts failing due to lack of memory. The code should probably be minimized to be able to figure anything out of it.

@ghostdogpr
Copy link
Contributor Author

Is there a way to print the generated code?
I use the following code but it doesn't get printed when this error occurs:

object PrintMacPass {
  inline def apply[T](inline any: T): T = ${ printMacImpl('any) }
  def printMacImpl[T: Type](any: Expr[T])(using qctx: Quotes): Expr[T] = {
    import qctx.reflect._
    println(Printer.TreeShortCode.show(any.asTerm))
    any
  }
}

If I were able to see what it generates I could probably understand why it's generating too much code.

@nicolasstucki
Copy link
Contributor

That will unfortunately not work as once the error is emitted we stop inlining. Hence that macro will not get expanded.

I instrumented a version of the compiler that will print what is being inlined. You may clone https://github.com/dotty-staging/dotty/tree/instument-inlining and then publish it locally by doing sbt scala3-bootstrapped/publishLocal. Then use 3.1.2-RC1-bin-SNAPSHOTas Scala 3 version in your build. You will need to increase-pagewidthand maybe set-color:never`. I ran it an got this output.

Or even better, transform your inline functions that use summonInline into proper macros. Then you can programmatically debug your own code.

@ghostdogpr
Copy link
Contributor Author

Thanks, that was super useful. I can understand what is going on.

The fact that I call explicitly import genericSchema.gen gives to this given a higher priority than the instances defined in the companion object of my typeclass. So instead of reusing instances, it generate instances for everything, including stuff like List, ::, etc (see below). That explains why it works if I remove import genericSchema.gen, but then I need to explicitly call gen for the missing instances because it won't generate them otherwise. I need to figure out a way so that gen has a lower priority than the rest.

      ==> inlining genericSchema.gen[caliban.federation.Federation.RepresentationsArgs]?
        ==> inlining SchemaDerivation_this.derived[caliban.federation.Federation.RepresentationsArgs]?
          ==> inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[caliban.federation.Federation.RepresentationsArgs]?
          <== inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[caliban.federation.Federation.RepresentationsArgs] = Nil:List[Any]
          ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
            ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[List[caliban.federation.Federation._Any]]?
            <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[List[caliban.federation.Federation._Any]] = List.apply[Any]([new SerialVersionUID(value = 3L) : Any]*):List[Any]
            ==> inlining genericSchema.gen[List[caliban.federation.Federation._Any]]?
              ==> inlining SchemaDerivation_this.derived[List[caliban.federation.Federation._Any]]?
                ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                  ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[::[caliban.federation.Federation._Any]]?
                  <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[::[caliban.federation.Federation._Any]] = Nil:List[Any]
                  ==> inlining genericSchema.gen[::[caliban.federation.Federation._Any]]?
                    ==> inlining SchemaDerivation_this.derived[::[caliban.federation.Federation._Any]]?
                      ==> inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[::[caliban.federation.Federation._Any]]?
                      <== inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[::[caliban.federation.Federation._Any]] = Nil:List[Any]
                      ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                        ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.federation.Federation._Any]?
                        <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.federation.Federation._Any] = Nil:List[Any]
                        ==> inlining genericSchema.gen[caliban.federation.Federation._Any]?
                          ==> inlining SchemaDerivation_this.derived[caliban.federation.Federation._Any]?
                            ==> inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[caliban.federation.Federation._Any]?
                            <== inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[caliban.federation.Federation._Any] = Nil:List[Any]
                            ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                              ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[String]?
                              <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[String] = Nil:List[Any]
                              ==> inlining SchemaDerivation_this.recurse[("fields" : String) *: EmptyTuple.type, caliban.InputValue *: EmptyTuple.type](index$proxy10.+(1))?
                                ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue]?
                                <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue] = Nil:List[Any]
                                ==> inlining genericSchema.gen[caliban.InputValue]?
                                  ==> inlining SchemaDerivation_this.derived[caliban.InputValue]?
                                    ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                                      ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue.ListValue]?
                                      <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue.ListValue] = Nil:List[Any]
                                      ==> inlining genericSchema.gen[caliban.InputValue.ListValue]?
                                        ==> inlining SchemaDerivation_this.derived[caliban.InputValue.ListValue]?
                                          ==> inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[caliban.InputValue.ListValue]?
                                          <== inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[caliban.InputValue.ListValue] = Nil:List[Any]
                                          ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                                            ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[List[caliban.InputValue]]?
                                            <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[List[caliban.InputValue]] = List.apply[Any]([new SerialVersionUID(value = 3L) : Any]*):List[Any]
                                            ==> inlining genericSchema.gen[List[caliban.InputValue]]?
                                              ==> inlining SchemaDerivation_this.derived[List[caliban.InputValue]]?
                                                ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                                                  ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[::[caliban.InputValue]]?
                                                  <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[::[caliban.InputValue]] = Nil:List[Any]
                                                  ==> inlining genericSchema.gen[::[caliban.InputValue]]?
                                                    ==> inlining SchemaDerivation_this.derived[::[caliban.InputValue]]?
                                                      ==> inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[::[caliban.InputValue]]?
                                                      <== inlining SchemaDerivation_this.inline$Macros$i4(caliban.schema.macros).annotations[::[caliban.InputValue]] = Nil:List[Any]
                                                      ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                                                        ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue]?
                                                        <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue] = Nil:List[Any]
                                                        ==> inlining caliban.schema.Schema.gen[caliban.InputValue]?
                                                          ==> inlining SchemaDerivation_this.derived[caliban.InputValue]?
                                                            ==> inlining SchemaDerivation_this.recurse[m.MirroredElemLabels, m.MirroredElemTypes](SchemaDerivation_this.recurse$default$1[m.MirroredElemLabels, m.MirroredElemTypes])?
                                                              ==> inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue.ListValue]?
                                                              <== inlining SchemaDerivation_this.inline$Macros$i1(caliban.schema.macros).annotations[caliban.InputValue.ListValue] = Nil:List[Any]
                                                              ==> inlining caliban.schema.Schema.gen[caliban.InputValue.ListValue]?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
itype:bug stat:needs minimization Needs a self contained minimization
Projects
None yet
Development

No branches or pull requests

2 participants