Skip to content

SIP-56: Better foundations for match types #18262

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

Merged
merged 17 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
c96d847
Introduce MatchTypeCaseSpec to categorize match type cases.
sjrd Jul 20, 2023
5260c60
Use new specced match types for class type constructors.
sjrd Nov 24, 2023
cc41d48
Use new specced match types for `scala.compiletime.int.S[n]`.
sjrd Aug 4, 2023
067b828
Short-circuit match type cases with missing captures in their patterns.
sjrd Nov 24, 2023
aa8d348
Use the specced match types for abstract tycons in patterns.
sjrd Aug 4, 2023
97725d7
Handle type member extractors as specced match types.
sjrd Aug 8, 2023
7ab7b0f
Report a compile error on illegal match types.
sjrd Nov 24, 2023
ec94ff5
Allow to reduce type member extractors when the member is a class.
sjrd Nov 24, 2023
1b2a16e
New implementation of `provablyDisjoint` to match SIP-56.
sjrd Aug 17, 2023
f432d08
Be more specific about higher-kinded types in provablyDisjoint.
sjrd Aug 29, 2023
c653793
Do not use provablyEmpty anymore; use S <: T + provablyDisjoint(S, T)…
sjrd Nov 24, 2023
16cf4f2
Add regression tests for old issues fixed with the new match types.
sjrd Aug 30, 2023
c8b4da8
Under -source:3.3 and below, always use the legacy match type algorithm.
sjrd Nov 24, 2023
2dd9f45
In type assigner for Apply, carry ErrorType's from the `fn`.
sjrd Nov 29, 2023
ec097a9
Fix 1 cause of infinite recursion in the new provablyDisjoint.
sjrd Dec 18, 2023
b5a4ca5
Demonstrate more potential unsoundness with a CCE reproducer.
sjrd Dec 8, 2023
c3b9d9b
Add comments that link to relevant parts of the spec of SIP-56.
sjrd Dec 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Allow to reduce type member extractors when the member is a class.
  • Loading branch information
sjrd committed Dec 18, 2023
commit ec94ff5f061f9abc66eda0a207438ae228f05300
22 changes: 9 additions & 13 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3371,19 +3371,15 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
stableScrut.member(typeMemberName) match
case denot: SingleDenotation if denot.exists =>
val info = denot.info match
case TypeAlias(alias) => alias
case info => info // Notably, RealTypeBounds, which will eventually give a MatchResult.NoInstances
if info.isInstanceOf[ClassInfo] then
/* The member is not an alias (we'll get Stuck instead of NoInstances,
* which is not ideal, but we cannot make a RealTypeBounds of ClassInfo).
*/
false
else
val infoRefersToSkolem = stableScrut.isInstanceOf[SkolemType] && stableScrut.occursIn(info)
val info1 =
if infoRefersToSkolem && !info.isInstanceOf[TypeBounds] then RealTypeBounds(info, info) // to trigger a MatchResult.NoInstances
else info
rec(capture, info1, variance = 0, scrutIsWidenedAbstract)
case TypeAlias(alias) => alias // Extract the alias
case ClassInfo(prefix, cls, _, _, _) => prefix.select(cls) // Re-select the class from the prefix
case info => info // Notably, RealTypeBounds, which will eventually give a MatchResult.NoInstances
val infoRefersToSkolem = stableScrut.isInstanceOf[SkolemType] && stableScrut.occursIn(info)
val info1 = info match
case info: TypeBounds => info // Will already trigger a MatchResult.NoInstances
case _ if infoRefersToSkolem => RealTypeBounds(info, info) // Explicitly trigger a MatchResult.NoInstances
case _ => info // We have a match
rec(capture, info1, variance = 0, scrutIsWidenedAbstract)
case _ =>
false
end rec
Expand Down
13 changes: 13 additions & 0 deletions tests/neg/match-type-enumeration-value-hack.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- [E172] Type Error: tests/neg/match-type-enumeration-value-hack.scala:11:40 ------------------------------------------
11 | summon[Suit#Value =:= EnumValue[Suit]] // error
| ^
| Cannot prove that Suit#Value =:= EnumValue[Suit].
|
| Note: a match type could not be fully reduced:
|
| trying to reduce EnumValue[Suit]
| failed since selector Suit
| does not uniquely determine parameter t in
| case EnumValueAux[t] => t
| The computed bounds for the parameter are:
| t >: ?1.Value <: ?1.Value
12 changes: 12 additions & 0 deletions tests/neg/match-type-enumeration-value-hack.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
type EnumValueAux[A] = ({ type Value }) { type Value = A }

type EnumValue[E <: Enumeration] = E match
case EnumValueAux[t] => t

// A class extending Enumeration does not yet define a concrete enumeration
class Suit extends Enumeration:
val Hearts, Diamonds, Clubs, Spades = Val()

object Test:
summon[Suit#Value =:= EnumValue[Suit]] // error
end Test
11 changes: 11 additions & 0 deletions tests/pos/match-type-enumeration-value-hack.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
type EnumValueAux[A] = ({ type Value }) { type Value = A }

type EnumValue[E <: Enumeration] = E match
case EnumValueAux[t] => t

object Suit extends Enumeration:
val Hearts, Diamonds, Clubs, Spades = Val()

object Test:
summon[Suit.Value =:= EnumValue[Suit.type]]
end Test