Skip to content

Regression in greenfossil/data-mapping - match type on method arguments #20149

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
WojciechMazur opened this issue Apr 10, 2024 · 2 comments
Closed

Comments

@WojciechMazur
Copy link
Contributor

Based on OpenCB failure in greenfossil/data-mapping - build logs

Compiler version

Last good release: 3.5.0-RC1-bin-20240403-ece87c3-NIGHTLY
First bad release: 3.5.0-RC1-bin-20240404-a7f00e2-NIGHTLY

Bisect points to 0bf43b2

Minimized code

trait Mapping[A] 

// Works if newMappings is defined as val/def 
def Test(newMappings: Mapping[?] *: Tuple) = 
  val boundFieldValues: Any *: Tuple =
    newMappings.map[[A] =>> Any] {
      [X] => (x: X) => x match
        case f: Mapping[t] => ???
    }

Output

-- [E007] Type Mismatch Error: /Users/wmazur/projects/scala3/bisect/test.scala:6:33 
6 |    newMappings.map[[A] =>> Any] {
  |    ^
  |Found:    Tuple.Map[(newMappings : Mapping[?] *: Tuple), [A] =>> Any]
  |Required: Any *: Tuple
  |
  |Note: a match type could not be fully reduced:
  |
  |  trying to reduce  Tuple.Map[(newMappings : Mapping[?] *: Tuple), [A] =>> Any]
  |  failed since selector (newMappings : Mapping[?] *: Tuple)
  |  does not uniquely determine parameters h, t in
  |    case h *: t => Any *: Tuple.Map[t, [A] =>> Any]
  |  The computed bounds for the parameters are:
  |    h <: Mapping[?]
  |    t <: Tuple
7 |      [X] => (x: X) => x match
8 |        case f: Mapping[t] => ???
9 |    }
  |
  | longer explanation available when compiling with `-explain`
1 error found

Expectation

Should compile

@WojciechMazur WojciechMazur added itype:bug area:match-types regression This worked in a previous version but doesn't anymore labels Apr 10, 2024
@sjrd
Copy link
Member

sjrd commented Apr 10, 2024

That's the way it is. Being able to follow the upper bound of a term parameter was unsound, as illustrated by #19746. Plugging soundness holes trumps not regressing.

If the result of match type expansion does not need to appear in the actual result type of the method, a solution can be declare a "copy" local val, as follows:

 trait Mapping[A] 

 // Works if newMappings is defined as val/def 
 def Test(newMappings: Mapping[?] *: Tuple) = 
+  val newMappings1 = newMappings
   val boundFieldValues: Any *: Tuple =
-    newMappings.map[[A] =>> Any] {
+    newMappings1.map[[A] =>> Any] {
       [X] => (x: X) => x match
         case f: Mapping[t] => ???
     }

This is sound because newMappings1 already has the widened type of newMappings, so the result type cannot leak as dependent on newMappings.

@sjrd sjrd added itype:invalid and removed itype:bug regression This worked in a previous version but doesn't anymore labels Apr 10, 2024
@sjrd sjrd closed this as not planned Won't fix, can't repro, duplicate, stale Apr 10, 2024
@chungonn
Copy link

chungonn commented Sep 8, 2024

That's the way it is. Being able to follow the upper bound of a term parameter was unsound, as illustrated by #19746. Plugging soundness holes trumps not regressing.

If the result of match type expansion does not need to appear in the actual result type of the method, a solution can be declare a "copy" local val, as follows:

 trait Mapping[A] 

 // Works if newMappings is defined as val/def 
 def Test(newMappings: Mapping[?] *: Tuple) = 
+  val newMappings1 = newMappings
   val boundFieldValues: Any *: Tuple =
-    newMappings.map[[A] =>> Any] {
+    newMappings1.map[[A] =>> Any] {
       [X] => (x: X) => x match
         case f: Mapping[t] => ???
     }

This is sound because newMappings1 already has the widened type of newMappings, so the result type cannot leak as dependent on newMappings.

Hi, I tried to compile our library against the release 3.5.0 and I hit the compilation error. I spent a bit of time going back to 3.4.0 to confirmed it is working. I recalled that it did work during an early 3.5.0 nightly build.

Thanks for the example code, I have rectified it. It all seems good now.

I have a question, isn't newMappings value is allocated in the stack space and that is technically the same as newMapping1?

val newMappings1: Mapping[?] *: Tuple = newMappings

chungonn added a commit to Greenfossil/data-mapping that referenced this issue Sep 8, 2024
chungonn added a commit to Greenfossil/data-mapping that referenced this issue Sep 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants