Skip to content

Bug at type inference for structural types. #12306

Closed
@shumy

Description

@shumy

Compiler version

3.0.0-RC1

Minimized code

class Record(private val fields: Map[String, Any]) extends Selectable:
  def this(elems: (String, Any)*) = this(elems.toMap)
  def selectDynamic(name: String): Any = fields(name)

  infix def ::[I <: Record, O >: this.type & I](record: I): O =
    Record(fields ++ record.fields).asInstanceOf[O]

  def debug() =
    val elems = fields.map{ case (key, value) => s"${key}: ${value.getClass.getSimpleName.toString}" }
    s"{ ${elems.mkString(", ")} }"

  def toJson() =
    val elems = fields.map{ case (key, value) => s"${key}: ${value}" }
    s"{ ${elems.mkString(", ")} }"

object Record:
  def of[T <: Record](elems: (String, Any)*) = Record(elems.toMap).asInstanceOf[T]
  def obj[I <: Object](obj: I) = obj.asInstanceOf[Record]


extension [L <: Object](left: L)
  infix def &[R <: Object, O >: L & R](right: R): O =
    (left.asInstanceOf[Record] :: right.asInstanceOf[Record]).asInstanceOf[O]

@main def hello =
  type One = { val one: Int }
  type Two = { val two: Int }
  type Extended = { val one: Int; val two: Int }

  val one: One = Record.of("one" -> 1)
  val two: Two = Record.of("two" -> 2)
  val v1: One & Two = one & two
  val v2 = one & two
  
  val v3: Extended = v1
  val v4: Extended = v2
  
  val v5: Extended = one & two

  val record = Record.obj(one & two)
  println(Record.obj(v2).toJson())

Output

Found:    (two : Two)
Required: Object{one: Int; two: Int}

Expectation

line 38: val v5: Extended = one & two should work in the same way this works:

  val v3: Extended = v1
  val v4: Extended = v2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions