Skip to content
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

Make aliases of MatchAliases normal TypeAliases #19871

Merged
merged 5 commits into from
Apr 8, 2024

Conversation

EugeneFlesselle
Copy link
Contributor

@EugeneFlesselle EugeneFlesselle commented Mar 4, 2024

Proposes to make isMatch true only for MatchTypes and higher-kinded abstraction of them.

As a result, code using isMatch to choose between a TypeAlias and MatchAlias will now use a TypeAlias when aliasing a MatchAlias. Which in turn allows for better de-aliasing, since dealias only de-aliases standard type aliases.

tryNormalize on AppliedType should only attempt reduction if there is an underlying match type. This could previously be identified by a MatchAlias tycon. We now need a recursive check.

Fixes #19821

@dwijnand
Copy link
Member

dwijnand commented Mar 5, 2024

Alternative to #19854

@EugeneFlesselle EugeneFlesselle force-pushed the match-alias branch 2 times, most recently from 5a6aa23 to 707eb77 Compare March 6, 2024 13:37
@EugeneFlesselle EugeneFlesselle changed the title [WIP] Make aliases of MatchAliases TypeAliases instead of MatchAliases [WIP] Make isMatch false for applied MatchAliases Mar 6, 2024
@EugeneFlesselle EugeneFlesselle changed the title [WIP] Make isMatch false for applied MatchAliases Make isMatch false for applied MatchAliases Mar 6, 2024
@EugeneFlesselle EugeneFlesselle marked this pull request as ready for review March 6, 2024 13:41
@EugeneFlesselle EugeneFlesselle force-pushed the match-alias branch 2 times, most recently from c794c5f to 93c3563 Compare March 6, 2024 13:47
@EugeneFlesselle EugeneFlesselle force-pushed the match-alias branch 3 times, most recently from dbd43b6 to add986b Compare March 7, 2024 11:38
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.

Here's two more places where I wonder whether we need change too:

  1. The MatchAlias type test in TypeOps.simplify
  2. The MatchAlias case in MatchType.InDisguise

Should those be if tp.isMatchAlias and case AliasingBounds(alias) if tp.isMatchAlias too?

@EugeneFlesselle
Copy link
Contributor Author

EugeneFlesselle commented Mar 11, 2024

@dwijnand For MatchType.InDisguise:

object InDisguise:
  def unapply(tp: AppliedType)(using Context): Option[MatchType] = tp match
    case AppliedType(tycon: TypeRef, args) => tycon.info match
      case MatchAlias(alias) => alias.applyIfParameterized(args) match
        case mt: MatchType => Some(mt)
        case _ => None
      case _ => None
    case _ => None

If I am not mistaken, the applyIfParameterized will only reduce a single application of a TypeRef tycon. So any cases that would match case AliasingBounds(alias) if tp.isMatchAlias which did not match case MatchAlias(alias) would then fail the second match in any case. So I think the cases matching MatchType.InDisguise remain the same with the changes.

I'm now wondering if you meant we might want to also accept these cases, independently of how they are affected by the aliasing changes ?

An equivalent change on main would then be

object InDisguise:
  def unapply(tp: AppliedType)(using Context): Option[MatchType] = tp match
    case AppliedType(tycon: TypeRef, args) => tycon.info match
      case MatchAlias(alias) => alias.applyIfParameterized(args) match
        case mt: MatchType => Some(mt)
         case MatchType.InDisguise(mt) => Some(mt)
        case _ => None
      case _ => None
    case _ => None

which doesn't seem to break anything.

Also, it looks like MatchType.InDisguise and underlyingMatchType would then be doing nearly the same thing, note that the latter uses superType which also does an applyIfParameterized. Maybe we only need one ?

@EugeneFlesselle
Copy link
Contributor Author

For TypeOps.simplify, I agree it should be if tp.isMatchAlias instead.

@dwijnand
Copy link
Member

Next is double-checking that we'll still function appropriately when we unpickle pre-3.4 tasty. I think it's dealt with the Unpickler change, right?

@EugeneFlesselle
Copy link
Contributor Author

Next is double-checking that we'll still function appropriately when we unpickle pre-3.4 tasty. I think it's dealt with the Unpickler change, right?

The changes in Unpickler don't do anything more than factoring out the if alias.isMatch then MatchAlias(alias) else TypeAlias(alias) logic. Independently of the changes made in the Unpickler, it uses the updated isMatch method. So it'll unpickle aliases in a way that is consistent with what the rest of code base expects. But differently from what they were before being pickled prior to the changes, which I assumed (but am not sure of) was okay.

@EugeneFlesselle
Copy link
Contributor Author

test performance please

1 similar comment
@mbovel
Copy link
Member

mbovel commented Mar 21, 2024

test performance please

@dottybot
Copy link
Member

performance test scheduled: 148 job(s) in queue, 1 running.

@dottybot
Copy link
Member

Performance test finished successfully:

Visit https://dotty-bench.epfl.ch/19871/ to see the changes.

Benchmarks is based on merging with main (a36849f)

@EugeneFlesselle EugeneFlesselle force-pushed the match-alias branch 2 times, most recently from 263119a to c2030ea Compare March 31, 2024 17:15
@EugeneFlesselle EugeneFlesselle changed the title Make isMatch false for applied MatchAliases Make aliases of MatchAliases normal TypeAliases Mar 31, 2024
@EugeneFlesselle EugeneFlesselle requested review from sjrd and odersky and removed request for sjrd April 1, 2024 14:07
This is necessary to ensure the implicit scope is consistent when involving match types, since they may or may not have been reduced before implicit search.
We can for example get different results when loading from tasty than when in the same run.

Fixes scala#20071
Make `isMatch` false for applied `MatchAlias`es,
i.e. true only for `MatchType`s and higher-kinded abstraction of them.

As a result, code using `isMatch` to choose between a `TypeAlias` and `MatchAlias`
will now use a `TypeAlias` when aliasing a `MatchAlias`.
Which in turn allows for better de-aliasing, since `dealias` only de-aliases standard type aliases.
The logic for this distinction has also been extracted to the common `AliasingBounds` supertype.

`tryNormalize` on `AppliedType`s should only attempt reduction if there is an underlying match type.
This could previously be identified by a `MatchAlias` tycon. We now need a recursive check.
`def underlyingMatchType` had an `isMatchAlias` guard for `AppliedType`s.
This used to be a quick check preventing unnecessary recursions and superType computations.

But `isMatchAlias` is now itself mutually recursive with `underlyingMatchType`,
so we cache it for AppliedTypes to alleviate this.
@EugeneFlesselle
Copy link
Contributor Author

EugeneFlesselle commented Apr 8, 2024

Note that this PR is now based on #20077,
because we get the same issue with neg/i15183 when updating def isAnchor.

@odersky odersky merged commit 1e8a653 into scala:main Apr 8, 2024
19 checks passed
EugeneFlesselle added a commit that referenced this pull request Apr 9, 2024
This already wasn't the case for unpickled match types,
which caused varying results for `ImplicitRunInfo#isAnchor`,
by not reaching the `isMatchAlias` condition.

Ensures both #20071 and #20136 each have the same result,
when compiled with a classpath dependency as when merged.
Note that they both still fail (20071 compiles but shouldn't),
but at least do so consistently.

Also update TreeUnpickler MATCHtpt doc to align with changes from #19871

Co-authored-by: Guillaume Martres <smarter@ubuntu.com>
@Kordyjan Kordyjan added this to the 3.5.0 milestone May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Match type scrutinee is not dealiased (enough)
6 participants