Skip to content

GADT with dependent type parameters causes pickler crash orphan parameter reference when using Mirror #23774

@eejbyfeldt

Description

@eejbyfeldt

Compiler version

3.7.2

Minimized code

enum Expr {
  case UpcastToIterable[T, C <: Iterable[T]]()
}

object Expr {
  summon[scala.deriving.Mirror.SumOf[Expr]]
}

Output (click arrow to expand)

 scalac expr_pickle_crash.scala
error when pickling type T
error when pickling type Iterable[T]
error when pickling type Expr.UpcastToIterable[Any, Iterable[T]]
error when pickling type Expr.UpcastToIterable[Any, Iterable[T]] *: EmptyTuple.type
error when pickling type  = Expr.UpcastToIterable[Any, Iterable[T]] *: EmptyTuple.type
error when pickling type scala.deriving.Mirror.Sum{
  type MirroredMonoType = Expr; type MirroredType = Expr;
    type MirroredLabel = ("Expr" : String);
    type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
      EmptyTuple.type
}
error when pickling type scala.deriving.Mirror.Sum{
  type MirroredMonoType = Expr; type MirroredType = Expr;
    type MirroredLabel = ("Expr" : String);
    type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
      EmptyTuple.type;
    type MirroredElemLabels = ("UpcastToIterable" : String) *: EmptyTuple.type
}
error when pickling tree 
  scala.deriving.Mirror.Sum{
    type MirroredMonoType = Expr; type MirroredType = Expr;
      type MirroredLabel = ("Expr" : String);
      type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
        EmptyTuple.type;
      type MirroredElemLabels = ("UpcastToIterable" : String) *: EmptyTuple.type
    }
 of class class dotty.tools.dotc.ast.Trees$InferredTypeTree
error when pickling tree val x$proxy1:
  
    scala.deriving.Mirror.Sum{
      type MirroredMonoType = Expr; type MirroredType = Expr;
        type MirroredLabel = ("Expr" : String);
        type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
          EmptyTuple.type;
        type MirroredElemLabels = ("UpcastToIterable" : String) *:
          EmptyTuple.type
    }
  
 =
  Expr.$asInstanceOf[
    
      scala.deriving.Mirror.Sum{
        type MirroredMonoType = Expr; type MirroredType = Expr;
          type MirroredLabel = ("Expr" : String);
          type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
            EmptyTuple.type;
          type MirroredElemLabels = ("UpcastToIterable" : String) *:
            EmptyTuple.type
      }
    
  ] of class class dotty.tools.dotc.ast.Trees$ValDef
error when pickling tree {
  val x$proxy1:
    
      scala.deriving.Mirror.Sum{
        type MirroredMonoType = Expr; type MirroredType = Expr;
          type MirroredLabel = ("Expr" : String);
          type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
            EmptyTuple.type;
          type MirroredElemLabels = ("UpcastToIterable" : String) *:
            EmptyTuple.type
      }
    
   =
    Expr.$asInstanceOf[
      
        scala.deriving.Mirror.Sum{
          type MirroredMonoType = Expr; type MirroredType = Expr;
            type MirroredLabel = ("Expr" : String);
            type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
              EmptyTuple.type;
            type MirroredElemLabels = ("UpcastToIterable" : String) *:
              EmptyTuple.type
        }
      
    ]
  x$proxy1
} of class class dotty.tools.dotc.ast.Trees$Inlined
error when pickling tree () extends Object(), scala.deriving.Mirror.Sum { this: Expr.type =>
  private def writeReplace(): AnyRef =
    new scala.runtime.ModuleSerializationProxy(classOf[Expr.type])
  final case class UpcastToIterable[T >: Nothing <: Any,
    C >: Nothing <: Iterable[T]]() extends Expr() {
    override def hashCode(): Int = -1772009433
    override def equals(x$0: Any): Boolean =
      (this eq x$0.$asInstanceOf[Object]) ||
        (x$0 match 
          {
            case x$0 @ _:Expr.UpcastToIterable[T, C] @unchecked => true
            case _ => false
          }
        )
    override def toString(): String = scala.runtime.ScalaRunTime._toString(this)
    override def canEqual(that: Any): Boolean =
      that.isInstanceOf[Expr.UpcastToIterable[T, C] @unchecked]
    override def productArity: Int = 0
    override def productPrefix: String = "UpcastToIterable"
    override def productElement(n: Int): Any =
      n match 
        {
          case _ => throw new IndexOutOfBoundsException(n.toString())
        }
    override def productElementName(n: Int): String =
      n match 
        {
          case _ => throw new IndexOutOfBoundsException(n.toString())
        }
    T
    C <: Iterable[T]
    def copy[T, C <: Iterable[T]](): Expr.UpcastToIterable[T, C] =
      new Expr.UpcastToIterable[T, C]()
    def ordinal: Int = 0
  }
  final lazy module val UpcastToIterable: Expr.UpcastToIterable =
    new Expr.UpcastToIterable()
  final module class UpcastToIterable() extends AnyRef(), 
    scala.deriving.Mirror.Product { this: Expr.UpcastToIterable.type =>
    private def writeReplace(): AnyRef =
      new scala.runtime.ModuleSerializationProxy(
        classOf[Expr.UpcastToIterable.type])
    def apply[T, C <: Iterable[T]](): Expr.UpcastToIterable[T, C] =
      new Expr.UpcastToIterable[T, C]()
    def unapply[T, C <: Iterable[T]](x$1: Expr.UpcastToIterable[T, C]): true =
      true
    override def toString: String = "UpcastToIterable"
    type MirroredMonoType = Expr.UpcastToIterable[? <: AnyKind, ? <: AnyKind]
    def fromProduct(x$0: Product): Expr.UpcastToIterable.MirroredMonoType =
      {
        new Expr.UpcastToIterable[Any, Iterable[Any]]()
      }
  }
  def fromOrdinal(ordinal: Int): Expr =
    throw 
      new NoSuchElementException(
        "enum Expr has no case with ordinal: " + ordinal.toString())
  {
    val x$proxy1:
      
        scala.deriving.Mirror.Sum{
          type MirroredMonoType = Expr; type MirroredType = Expr;
            type MirroredLabel = ("Expr" : String);
            type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
              EmptyTuple.type;
            type MirroredElemLabels = ("UpcastToIterable" : String) *:
              EmptyTuple.type
        }
      
     =
      Expr.$asInstanceOf[
        
          scala.deriving.Mirror.Sum{
            type MirroredMonoType = Expr; type MirroredType = Expr;
              type MirroredLabel = ("Expr" : String);
              type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]]
                *: EmptyTuple.type;
              type MirroredElemLabels = ("UpcastToIterable" : String) *:
                EmptyTuple.type
          }
        
      ]
    x$proxy1
  }
  type MirroredMonoType = Expr
  def ordinal(x$0: Expr.MirroredMonoType): Int = x$0.ordinal
} of class class dotty.tools.dotc.ast.Trees$Template
error when pickling tree @SourceFile("expr_pickle_crash.scala") final module class Expr() extends
  Object(), scala.deriving.Mirror.Sum { this: Expr.type =>
  private def writeReplace(): AnyRef =
    new scala.runtime.ModuleSerializationProxy(classOf[Expr.type])
  final case class UpcastToIterable[T >: Nothing <: Any,
    C >: Nothing <: Iterable[T]]() extends Expr() {
    override def hashCode(): Int = -1772009433
    override def equals(x$0: Any): Boolean =
      (this eq x$0.$asInstanceOf[Object]) ||
        (x$0 match 
          {
            case x$0 @ _:Expr.UpcastToIterable[T, C] @unchecked => true
            case _ => false
          }
        )
    override def toString(): String = scala.runtime.ScalaRunTime._toString(this)
    override def canEqual(that: Any): Boolean =
      that.isInstanceOf[Expr.UpcastToIterable[T, C] @unchecked]
    override def productArity: Int = 0
    override def productPrefix: String = "UpcastToIterable"
    override def productElement(n: Int): Any =
      n match 
        {
          case _ => throw new IndexOutOfBoundsException(n.toString())
        }
    override def productElementName(n: Int): String =
      n match 
        {
          case _ => throw new IndexOutOfBoundsException(n.toString())
        }
    T
    C <: Iterable[T]
    def copy[T, C <: Iterable[T]](): Expr.UpcastToIterable[T, C] =
      new Expr.UpcastToIterable[T, C]()
    def ordinal: Int = 0
  }
  final lazy module val UpcastToIterable: Expr.UpcastToIterable =
    new Expr.UpcastToIterable()
  final module class UpcastToIterable() extends AnyRef(), 
    scala.deriving.Mirror.Product { this: Expr.UpcastToIterable.type =>
    private def writeReplace(): AnyRef =
      new scala.runtime.ModuleSerializationProxy(
        classOf[Expr.UpcastToIterable.type])
    def apply[T, C <: Iterable[T]](): Expr.UpcastToIterable[T, C] =
      new Expr.UpcastToIterable[T, C]()
    def unapply[T, C <: Iterable[T]](x$1: Expr.UpcastToIterable[T, C]): true =
      true
    override def toString: String = "UpcastToIterable"
    type MirroredMonoType = Expr.UpcastToIterable[? <: AnyKind, ? <: AnyKind]
    def fromProduct(x$0: Product): Expr.UpcastToIterable.MirroredMonoType =
      {
        new Expr.UpcastToIterable[Any, Iterable[Any]]()
      }
  }
  def fromOrdinal(ordinal: Int): Expr =
    throw 
      new NoSuchElementException(
        "enum Expr has no case with ordinal: " + ordinal.toString())
  {
    val x$proxy1:
      
        scala.deriving.Mirror.Sum{
          type MirroredMonoType = Expr; type MirroredType = Expr;
            type MirroredLabel = ("Expr" : String);
            type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]] *:
              EmptyTuple.type;
            type MirroredElemLabels = ("UpcastToIterable" : String) *:
              EmptyTuple.type
        }
      
     =
      Expr.$asInstanceOf[
        
          scala.deriving.Mirror.Sum{
            type MirroredMonoType = Expr; type MirroredType = Expr;
              type MirroredLabel = ("Expr" : String);
              type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]]
                *: EmptyTuple.type;
              type MirroredElemLabels = ("UpcastToIterable" : String) *:
                EmptyTuple.type
          }
        
      ]
    x$proxy1
  }
  type MirroredMonoType = Expr
  def ordinal(x$0: Expr.MirroredMonoType): Int = x$0.ordinal
} of class class dotty.tools.dotc.ast.Trees$TypeDef
error when pickling tree package <empty> {
  @SourceFile("expr_pickle_crash.scala") @Child[Expr.UpcastToIterable] sealed
    abstract class Expr() extends Object(), scala.reflect.Enum {
    import Expr.UpcastToIterable
  }
  final lazy module val Expr: Expr = new Expr()
  @SourceFile("expr_pickle_crash.scala") final module class Expr() extends
    Object(), scala.deriving.Mirror.Sum { this: Expr.type =>
    private def writeReplace(): AnyRef =
      new scala.runtime.ModuleSerializationProxy(classOf[Expr.type])
    final case class UpcastToIterable[T >: Nothing <: Any,
      C >: Nothing <: Iterable[T]]() extends Expr() {
      override def hashCode(): Int = -1772009433
      override def equals(x$0: Any): Boolean =
        (this eq x$0.$asInstanceOf[Object]) ||
          (x$0 match 
            {
              case x$0 @ _:Expr.UpcastToIterable[T, C] @unchecked => true
              case _ => false
            }
          )
      override def toString(): String =
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean =
        that.isInstanceOf[Expr.UpcastToIterable[T, C] @unchecked]
      override def productArity: Int = 0
      override def productPrefix: String = "UpcastToIterable"
      override def productElement(n: Int): Any =
        n match 
          {
            case _ => throw new IndexOutOfBoundsException(n.toString())
          }
      override def productElementName(n: Int): String =
        n match 
          {
            case _ => throw new IndexOutOfBoundsException(n.toString())
          }
      T
      C <: Iterable[T]
      def copy[T, C <: Iterable[T]](): Expr.UpcastToIterable[T, C] =
        new Expr.UpcastToIterable[T, C]()
      def ordinal: Int = 0
    }
    final lazy module val UpcastToIterable: Expr.UpcastToIterable =
      new Expr.UpcastToIterable()
    final module class UpcastToIterable() extends AnyRef(), 
      scala.deriving.Mirror.Product { this: Expr.UpcastToIterable.type =>
      private def writeReplace(): AnyRef =
        new scala.runtime.ModuleSerializationProxy(
          classOf[Expr.UpcastToIterable.type])
      def apply[T, C <: Iterable[T]](): Expr.UpcastToIterable[T, C] =
        new Expr.UpcastToIterable[T, C]()
      def unapply[T, C <: Iterable[T]](x$1: Expr.UpcastToIterable[T, C]): true
         = true
      override def toString: String = "UpcastToIterable"
      type MirroredMonoType = Expr.UpcastToIterable[? <: AnyKind, ? <: AnyKind]
      def fromProduct(x$0: Product): Expr.UpcastToIterable.MirroredMonoType =
        {
          new Expr.UpcastToIterable[Any, Iterable[Any]]()
        }
    }
    def fromOrdinal(ordinal: Int): Expr =
      throw 
        new NoSuchElementException(
          "enum Expr has no case with ordinal: " + ordinal.toString())
    {
      val x$proxy1:
        
          scala.deriving.Mirror.Sum{
            type MirroredMonoType = Expr; type MirroredType = Expr;
              type MirroredLabel = ("Expr" : String);
              type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]]
                *: EmptyTuple.type;
              type MirroredElemLabels = ("UpcastToIterable" : String) *:
                EmptyTuple.type
          }
        
       =
        Expr.$asInstanceOf[
          
            scala.deriving.Mirror.Sum{
              type MirroredMonoType = Expr; type MirroredType = Expr;
                type MirroredLabel = ("Expr" : String);
                type MirroredElemTypes = Expr.UpcastToIterable[Any, Iterable[T]]
                   *: EmptyTuple.type;
                type MirroredElemLabels = ("UpcastToIterable" : String) *:
                  EmptyTuple.type
            }
          
        ]
      x$proxy1
    }
    type MirroredMonoType = Expr
    def ordinal(x$0: Expr.MirroredMonoType): Int = x$0.ordinal
  }
} of class class dotty.tools.dotc.ast.Trees$PackageDef

  unhandled exception while running pickler on expr_pickle_crash.scala

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/scala/scala3/issues/new/choose
  For non-enriched exceptions, compile with -Xno-enrich-error-messages.


     while compiling: expr_pickle_crash.scala
        during phase: pickler
                mode: Mode(ImplicitsEnabled)
     library version: version 2.13.16
    compiler version: version 3.7.2
            settings: 

Exception in thread "main" java.lang.AssertionError: assertion failed: orphan parameter reference: TypeParamRef(T)
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:318)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:183)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$2(TreePickler.scala:204)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:204)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:183)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$2(TreePickler.scala:204)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:204)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:183)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$2(TreePickler.scala:204)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:204)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:183)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:279)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:183)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:271)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:183)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:270)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:183)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:716)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTpt(TreePickler.scala:352)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef(TreePickler.scala:382)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:647)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$11(TreePickler.scala:619)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:617)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats$$anonfun$2(TreePickler.scala:423)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats(TreePickler.scala:423)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:698)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef(TreePickler.scala:381)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:664)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats$$anonfun$2(TreePickler.scala:423)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats(TreePickler.scala:423)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:714)
	at dotty.tools.dotc.core.tasty.TreePickler.pickle$$anonfun$1(TreePickler.scala:946)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.tasty.TreePickler.pickle(TreePickler.scala:944)
	at dotty.tools.dotc.transform.Pickler.run$$anonfun$1$$anonfun$1(Pickler.scala:306)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.transform.Pickler.run$$anonfun$1(Pickler.scala:279)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.transform.Pickler.run(Pickler.scala:278)
	at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:383)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:376)
	at dotty.tools.dotc.transform.Pickler.runPhase$1(Pickler.scala:392)
	at dotty.tools.dotc.transform.Pickler.runOn(Pickler.scala:398)
	at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:368)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1324)
	at dotty.tools.dotc.Run.runPhases$1(Run.scala:361)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1$$anonfun$2(Run.scala:408)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1$$anonfun$adapted$1(Run.scala:408)
	at scala.Function0.apply$mcV$sp(Function0.scala:42)
	at dotty.tools.dotc.Run.showProgress(Run.scala:470)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:408)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:420)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:420)
	at dotty.tools.dotc.Run.compileSources(Run.scala:307)
	at dotty.tools.dotc.Run.compile(Run.scala:292)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:37)
	at dotty.tools.dotc.Driver.process(Driver.scala:201)
	at dotty.tools.dotc.Driver.process(Driver.scala:169)
	at dotty.tools.dotc.Driver.process(Driver.scala:181)
	at dotty.tools.dotc.Driver.main(Driver.scala:211)
	at dotty.tools.MainGenericCompiler$.run$1(MainGenericCompiler.scala:160)
	at dotty.tools.MainGenericCompiler$.main(MainGenericCompiler.scala:184)
	at dotty.tools.MainGenericCompiler.main(MainGenericCompiler.scala)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at coursier.bootstrap.launcher.a.a(Unknown Source)
	at coursier.bootstrap.launcher.Launcher.main(Unknown Source)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions