Skip to content

Fix Tuple.toList return type #12772

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
wants to merge 2 commits into from
Closed

Conversation

nicolasstucki
Copy link
Contributor

This method failed for any subtype of Tuple.
It only worked for Tuple and TupleN as these define their own toList.

Fixes #12721

@sjrd
Copy link
Member

sjrd commented Jun 9, 2021

This change is not forward nor backward TASTy compatible. It can break existing inline defs that successfully call this method today.

@nicolasstucki nicolasstucki force-pushed the fix-#12721 branch 2 times, most recently from 5d158f8 to cf2b94e Compare June 10, 2021 07:10
@nicolasstucki nicolasstucki self-assigned this Jun 10, 2021
@nicolasstucki
Copy link
Contributor Author

@sjrd in which version would we be able to fix this without breaking compatibility?

We could also try to special-case it in the compiler so that if we have a reference to the old one we adapt it before expanding it.

@sjrd
Copy link
Member

sjrd commented Jun 14, 2021

in which version would we be able to fix this without breaking compatibility?

As currently proposed, not before Scala 4. (or 3.T)

We could also try to special-case it in the compiler so that if we have a reference to the old one we adapt it before expanding it.

That is a possibility, but it would have to enter the TASTy spec, because if any other tool unpickles that, it will have to perform the same fix. This is going to be super tricky.

@smarter
Copy link
Member

smarter commented Jun 14, 2021

What about making the old toList private[scala] (the tasty unpickler doesn't do accessibility checks so this is tasty-compatible) and adding a new toList as an extension method?

@sjrd
Copy link
Member

sjrd commented Jun 14, 2021

I guess we can try that.

@dwijnand
Copy link
Member

If that doesn't work, give EmptyTuple, NonEmptyTuple, *: their own toList methods?

Copy link
Member

@dwijnand dwijnand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently: not forward nor backward TASTy compatible

@soronpo
Copy link
Contributor

soronpo commented Jul 5, 2021

Currently: not forward nor backward TASTy compatible

Exactly why I was worried 3.0 was released so soon.

@nicolasstucki
Copy link
Contributor Author

If that doesn't work, give EmptyTuple, NonEmptyTuple, *: their own toList methods?

That did not work as we would be trying to override a final method. If I change the signature, at call site, it complains due to an ambiguity between the two toList.

@nicolasstucki nicolasstucki force-pushed the fix-#12721 branch 2 times, most recently from ea1f66a to 670b360 Compare July 28, 2021 09:02
// `inline def toList[This >: this.type <: Tuple]: List[Union[This]]`
/** Create a copy this tuple as a List */
extension [This <: Tuple](inline tuple: This)
inline def toList: List[Union[This]] =
Copy link
Member

@smarter smarter Jul 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between this and List[Union[tuple.type]] ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would fail with

3 |  (??? : Tuple).toList.map(bar)
  |  ^^^^^^^^^^^^^^^^^^^^
  |  Tuple is not a valid singleton type, since it is not an immutable path
  | This location contains code that was inlined from Tuple.scala:246

Also, the source of the original bug was caused by using the this.type instead of the type parameter.

Copy link
Member

@smarter smarter Jul 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tuple is not a valid singleton type, since it is not an immutable path

I find it weird that using a singleton type in the method result type would produce this error at use-site, is this a bug in the interaction between match types and singleton types? /cc @OlivierBlanvillain

Copy link
Contributor Author

@nicolasstucki nicolasstucki Jul 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it is because the prefix is not a singleton type and hence we have no way to refer to tuple.type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like it's widening too early? To me Tuple isn't the type that should be singleton, it's the value (??? : Tuple) that should be. Put in two lines:

val foo = ??? : Tuple
foo.toList.map(bar)

I expect tuple.type=foo.type not Tuple.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what I'm trying to say is I think this PR is working around a problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the prefix is not a singleton type and hence we have no way to refer to tuple.type.

That's not a problem normally: if the prefix is not a singleton type and we need it to be, then we skolemize it, but I haven't thought about how that logic is supposed to interact with match types: https://github.com/lampepfl/dotty/blob/e59c5ea77e4a498cd3a196f6eb1fc6a6b4dab05e/compiler/src/dotty/tools/dotc/core/TypeOps.scala#L36-L43

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we are missing some skolemization for this case

This method failed for any subtype of `Tuple`.
It only worked for `Tuple` and `TupleN` as these define their own `toList`.

Fixes scala#12721
This should in theory be backwards TASTy compatible.

Fixes scala#12721
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash from mapping on NonEmptyTuple.toList
5 participants