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

Update unreducible match types error reporting #19954

Merged
merged 7 commits into from
Mar 27, 2024

Commits on Mar 26, 2024

  1. Add regression tests

    EugeneFlesselle committed Mar 26, 2024
    Configuration menu
    Copy the full SHA
    7b69d33 View commit details
    Browse the repository at this point in the history
  2. Revert "ErrorType instead of throwing in match type "no cases""

    This reverts commit 9ae1598
    
    Note that the changes in Typer:
    ```
    val unsimplifiedType = result.tpe
    simplify(result, pt, locked)
    result.tpe.stripTypeVar match
      case e: ErrorType if !unsimplifiedType.isErroneous =>
        errorTree(xtree, e.msg, xtree.srcPos)
      case _ => result
    ```
    cannot be reverted yet since the MatchReducer now also reduces to an `ErrorType` for MatchTypeLegacyPatterns, introduced after 9ae1598.
    EugeneFlesselle committed Mar 26, 2024
    Configuration menu
    Copy the full SHA
    7460ab3 View commit details
    Browse the repository at this point in the history
  3. Update check-files and remove i18488.scala

    i18488.scala was only passing because of the bug in the MatchReducer,
    as we can see in the subtyping trace:
    ```
    ==> isSubType TableQuery[BaseCrudRepository.this.EntityTable] <:< Query[BaseCrudRepository.this.EntityTable, E[Option]]?
      ==> isSubType Query[BaseCrudRepository.this.EntityTable, Extract[BaseCrudRepository.this.EntityTable]] <:<
                    Query[BaseCrudRepository.this.EntityTable, E[Option]] (left is approximated)?
        ==> isSubType E[Option] <:< Extract[BaseCrudRepository.this.EntityTable]?
          ==> isSubType [T[_$1]] =>> Any <:< Extract?
            ==> isSubType Any <:< Extract[T]?
              ==> isSubType Any <:< T match { case AbstractTable[t] => t } <: t (right is approximated)?
                ==> isSubType Any <:< <error Match type reduction failed since selector T
                                       matches none of the cases
                                       case AbstractTable[t] => t> (right is approximated)?
                <== isSubType Any <:< <error Match type reduction failed since selector T
                                       matches none of the cases
                                       case AbstractTable[t] => t> (right is approximated) = true
              <== isSubType Any <:< T match { case AbstractTable[t] => t } <: t (right is approximated) = true
            <== isSubType Any <:< Extract[T] = true
          <== isSubType [T[_$1]] =>> Any <:< Extract = true
          ...
        <== isSubType Extract[BaseCrudRepository.this.EntityTable] <:< E[Option] = true
      <== isSubType Query[BaseCrudRepository.this.EntityTable, Extract[BaseCrudRepository.this.EntityTable]] <:<
                    Query[BaseCrudRepository.this.EntityTable, E[Option]] (left is approximated) = true
    <== isSubType TableQuery[BaseCrudRepository.this.EntityTable] <:< Query[BaseCrudRepository.this.EntityTable, E[Option]] = true
    ```
    EugeneFlesselle committed Mar 26, 2024
    Configuration menu
    Copy the full SHA
    5becaac View commit details
    Browse the repository at this point in the history
  4. Make match types with no matching cases not an error

    Modify the MatchReducer to return NoType in the case of no matches, rather than throwing a MatchTypeReductionError.
    This makes it consistent with the other match type reduction failures, where being stuck does not result in an error, but simply in an unreduced match type.
    
    We still get the explanations of the underlying error in the MatchTypeTrace, but in positions which need the reduction for conformance, rather than at application site of the match type.
    EugeneFlesselle committed Mar 26, 2024
    Configuration menu
    Copy the full SHA
    d7946bf View commit details
    Browse the repository at this point in the history
  5. Update check-files and error annotations

    The diff in neg/10349.scala is quite interesting.
    With a few intermediate values:
    ```scala
    type First[X] = X match
     case Map[_, v] => First[Option[v]]
    
    def first[X](x: X): First[X] = x match
     case x: Map[k, v] =>
     val hdOpt: Option[v] = x.values.headOption
     first(hdOpt): First[Option[v]] // error only before changes
    ```
    This now type-checks but will fail at runtime because of the in-exhaustivity of the match expression.
    Perhaps we should add some additional condition in `isMatchTypeShaped` to account for this, or at least emit a warning ?
    EugeneFlesselle committed Mar 26, 2024
    Configuration menu
    Copy the full SHA
    61c2832 View commit details
    Browse the repository at this point in the history
  6. Only record in MatchTypeTrace if not previously attempted

    `recurseWith` can be called with the same scrutinee (even if match type reduction is cached) if it is an applied match alias
    
    For example, `Tuple.Head[Tuple.Tail[T]]` will attempt to reduce `Tuple.Tail[T]` twice:
    - once as an argument of the match alias `Head`, and
    - once as a scrutinee in body of `Head` (after the substitution).
    EugeneFlesselle committed Mar 26, 2024
    Configuration menu
    Copy the full SHA
    2329236 View commit details
    Browse the repository at this point in the history
  7. Do match type reduction atPhaseNoLater than ElimOpaque

    If a match type pattern is an opaque type, we use its bounds when checking the validity of the pattern.
    Following the ElimOpaque phase however, the pattern is beta-reduced (as normal applied type aliases), which may result in an illegal pattern.
    EugeneFlesselle committed Mar 26, 2024
    Configuration menu
    Copy the full SHA
    2beb67e View commit details
    Browse the repository at this point in the history