Scala 3: how do we make a lambda type conform to a subtype?

I am trying to upgrade some 3.2.2 macro code to 3.3.1. During this “upgrade”, the following lines:

  type HasName1 = [n] =>> [x] =>> x match {
    case n => true
    case _ => false
  }
  summon[HasName1["foo"]["foo"] =:= true]
  summon[NotGiven[HasName1["foo"]["bar"] =:= true]]
  summon[Tuple.Filter[(1, "foo", 2, "bar"), HasName1["foo"]] =:= Tuple1["foo"]]

generate the error:

[error] 118 |  summon[Tuple.Filter[(1, "foo", 2, "bar"), HasName1["foo"]] =:= Tuple1["foo"]]
[error]     |                                            ^
[error]     |Type argument data.Data1.HasName1[("foo" : String)] does not conform to upper bound [_] =>> Boolean
[error]     |
[error]     |Note: a match type could not be fully reduced:
[error]     |
[error]     |  trying to reduce  data.Data1.HasName1[("foo" : String)]
[error]     |---------------------------------------------------------------------------
[error]     | Explanation (enabled by `-explain`)
[error]     |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[error]     | I tried to show that
[error]     |   data.Data1.HasName1[("foo" : String)]
[error]     | conforms to
[error]     |   [_] =>> Boolean
[error]     | but the comparison trace ended with `false`:
[error]     |
[error]     |   ==> data.Data1.HasName1[("foo" : String)]  <:  [_] =>> Boolean
[error]     |     ==> [x] =>> data.Data1.HasName1[("foo" : String)][x]  <:  [_] =>> Boolean
[error]     |       ==> type bounds []  <:  type bounds []
[error]     |       <== type bounds []  <:  type bounds [] = true
[error]     |       ==> data.Data1.HasName1[("foo" : String)][x]  <:  Boolean
[error]     |         ==> x match {   case ("foo" : String) => (true : Boolean)   case Any => (false : Boolean) }  <:  Boolean
[error]     |           ==> Any  <:  Boolean
[error]     |           <== Any  <:  Boolean = false
[error]     |         <== x match {   case ("foo" : String) => (true : Boolean)   case Any => (false : Boolean) }  <:  Boolean = false
[error]     |       <== data.Data1.HasName1[("foo" : String)][x]  <:  Boolean = false
[error]     |     <== [x] =>> data.Data1.HasName1[("foo" : String)][x]  <:  [_] =>> Boolean = false
[error]     |     ==> [x] =>>   x match {     case ("foo" : String) => (true : Boolean)     case Any => (false : Boolean)   }  <:  [_] =>> Boolean
[error]     |       ==> type bounds []  <:  type bounds []
[error]     |       <== type bounds []  <:  type bounds [] = true
[error]     |       ==> x match {   case ("foo" : String) => (true : Boolean)   case Any => (false : Boolean) }  <:  Boolean
[error]     |         ==> Any  <:  Boolean
[error]     |         <== Any  <:  Boolean = false
[error]     |       <== x match {   case ("foo" : String) => (true : Boolean)   case Any => (false : Boolean) }  <:  Boolean = false
[error]     |     <== [x] =>>   x match {     case ("foo" : String) => (true : Boolean)     case Any => (false : Boolean)   }  <:  [_] =>> Boolean = false
[error]     |   <== data.Data1.HasName1[("foo" : String)]  <:  [_] =>> Boolean = false
[error]     |
[error]     | The tests were made under the empty constraint
[error]      ---------------------------------------------------------------------------

The following works:

  type HasName[n,x] <: Boolean = x match {
    case n => true
    case _ => false
  }
  summon[HasName["foo", "foo"] =:= true]
  summon[NotGiven[HasName["foo", "bar"] =:= true]]
  summon[Tuple.Filter[(1, "foo", 2, "bar"), [X] =>> HasName["foo",X]] =:= Tuple1["foo"]]

So how can I change the type lambda to conform to [_] =>> Boolean Adding <: Boolean to type HasName1 does not work.

TIA.

Looks like a regression to me, I’ve created an issue to track progress and discussions on this issue. As a temporal workaround you can use Scala 3.3.0 (does not have this regression) instead of 3.3.1. The earliest the fix can be applied is 3.3.3 which is ~6 weeks from now.

2 Likes