Skip to content

Match type fails to reduce when it doesn't look like it needs to reduce #21391

Open
@s5bug

Description

@s5bug

Compiler version

3.3.3
3.4.2
3.5.0-RC7

Minimized code

enum Typ {
  case Fun[L <: Typ, R <: Typ](l: L, r: R)
}

enum Expr[T <: Typ] {
  case Fun[L <: Typ, R <: Typ](body: Expr[R]) extends Expr[Typ.Fun[L, R]]
}

type Interpreted[T <: Typ] = T match {
  case Typ.Fun[l, r] => Function1[Interpreted[l], Interpreted[r]]
}

def interpret[T <: Typ](e: Expr[T]): Interpreted[T] = e match {
  case f: Expr.Fun[l, r] =>
    (i: Interpreted[l]) => interpret(f.body)
}

Output

-- [E007] Type Mismatch Error: -------------------------------------------------
3 |    (i: Interpreted[l]) => interpret(f.body)
  |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |Found:    Interpreted[l] => Interpreted[r]
  |Required: Interpreted[T]
  |
  |where:    T is a type in method interpret which is an alias of Typ.Fun[l, r]
  |          l is a type in method interpret with bounds <: Typ
  |          r is a type in method interpret with bounds <: Typ
  |
  |
  |Note: a match type could not be fully reduced:
  |
  |  trying to reduce  Interpreted[l]
  |  failed since selector l
  |  does not match  case Typ.Fun[l, r] => Interpreted[l] => Interpreted[r]
  |  and cannot be shown to be disjoint from it either.
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  |
  | Tree: {
  |   def $anonfun(i: Interpreted[l]): Interpreted[r] =
  |     {
  |       interpret[r](f.body)
  |     }
  |   closure($anonfun)
  | }
  | I tried to show that
  |   Interpreted[l] => Interpreted[r]
  | conforms to
  |   Interpreted[T]
  | but none of the attempts shown below succeeded:
  |
  |   ==> Interpreted[l] => Interpreted[r]  <:  Interpreted[T]
  |     ==> Interpreted[l] => Interpreted[r]  <:  T match {
  |    case Typ.Fun[l, r] => Interpreted[l] => Interpreted[r]
  |  }  = false
  |
  | The tests were made under the empty constraint
   -----------------------------------------------------------------------------
1 error found

Expectation

I would want to believe that the knowledge of T is a type in method interpret which is an alias of Typ.Fun[l, r] would cause the trace to be the following:

 ==> Interpreted[l] => Interpreted[r]  <:  Interpreted[T]
   ==> Interpreted[l] => Interpreted[r]  <:  T match {
  case Typ.Fun[l, r] => Interpreted[l] => Interpreted[r]
}
     ==> Interpreted[l] => Interpreted[r] <: Interpreted[l] => Interpreted[r]

Otherwise I don't see how it's possible to create a lambda for Interpreted[l] => Interpreted[r]/how to use Interpreted[l] as a parameter type.

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