Skip to content

Commit 5086978

Browse files
Merge pull request #11263 from dotty-staging/fix-11247
Widen irreducible match type aliases to their bounds
2 parents 9c9d4ec + 3ab52e3 commit 5086978

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,13 +366,28 @@ trait ConstraintHandling {
366366
if (tpw eq tp) || dropped.forall(_ frozen_<:< tpw) then tp else tpw
367367
end dropTransparentTraits
368368

369+
/** If `tp` is an applied match type alias which is also an unreducible application
370+
* of a higher-kinded type to a wildcard argument, widen to the match type's bound,
371+
* in order to avoid an unreducible application of higher-kinded type ... in inferred type"
372+
* error in PostTyper. Fixes #11246.
373+
*/
374+
def widenIrreducible(tp: Type)(using Context): Type = tp match
375+
case tp @ AppliedType(tycon, _) if tycon.isLambdaSub && tp.hasWildcardArg =>
376+
tp.superType match
377+
case MatchType(bound, _, _) => bound
378+
case _ => tp
379+
case _ =>
380+
tp
381+
369382
/** Widen inferred type `inst` with upper `bound`, according to the following rules:
370383
* 1. If `inst` is a singleton type, or a union containing some singleton types,
371-
* widen (all) the singleton type(s), provided the result is a subtype of `bound`
384+
* widen (all) the singleton type(s), provided the result is a subtype of `bound`.
372385
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
373386
* 2. If `inst` is a union type, approximate the union type from above by an intersection
374387
* of all common base types, provided the result is a subtype of `bound`.
375-
* 3. drop transparent traits from intersections (see @dropTransparentTraits)
388+
* 3. Widen some irreducible applications of higher-kinded types to wildcard arguments
389+
* (see @widenIrreducible).
390+
* 4. Drop transparent traits from intersections (see @dropTransparentTraits).
376391
*
377392
* Don't do these widenings if `bound` is a subtype of `scala.Singleton`.
378393
* Also, if the result of these widenings is a TypeRef to a module class,
@@ -397,7 +412,7 @@ trait ConstraintHandling {
397412

398413
val wideInst =
399414
if isSingleton(bound) then inst
400-
else dropTransparentTraits(widenOr(widenSingle(inst)), bound)
415+
else dropTransparentTraits(widenIrreducible(widenOr(widenSingle(inst))), bound)
401416
wideInst match
402417
case wideInst: TypeRef if wideInst.symbol.is(Module) =>
403418
TermRef(wideInst.prefix, wideInst.symbol.sourceModule)

compiler/test/dotc/pos-test-pickling.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ i7872.scala
3333
6709.scala
3434
6687.scala
3535
i11236.scala
36+
i11247.scala
3637

3738
# Opaque type
3839
i5720.scala

tests/pos/i11247.scala

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import annotation.showAsInfix
2+
import scala.compiletime._
3+
4+
class TupleKOps {
5+
6+
7+
def tupleMerge(tuple1: TupleK, tuple2: TupleK): TupleK = ???
8+
9+
def tupleMergeSort(tuple: TupleK): TupleK =
10+
if (tuple.size <= 1) tuple
11+
else {
12+
val (tuple1, tuple2) = tuple.splitAt(tuple.size / 2)
13+
// val (tuple1: TupleK, tuple2: TupleK) = tuple.splitAt(tuple.size / 2) // ok
14+
val (sorted1, sorted2) = (tupleMergeSort(tuple1), tupleMergeSort(tuple2))
15+
tupleMerge(sorted1, sorted2)
16+
}
17+
18+
}
19+
20+
sealed trait TupleK {
21+
import TupleK._
22+
/*inline*/ def size[This >: this.type <: TupleK]: Size[This] = ???
23+
/*inline*/ def splitAt[This >: this.type <: TupleK](n: Int): Split[This, n.type] = ???
24+
}
25+
26+
object TupleK {
27+
type Size[X <: TupleK] <: Int = X match {
28+
case EmptyTupleK => 0
29+
case x #: xs => S[Size[xs]]
30+
}
31+
type Take[T <: TupleK, N <: Int] <: TupleK = N match {
32+
case 0 => EmptyTupleK
33+
case S[n1] => T match {
34+
case EmptyTupleK => EmptyTupleK
35+
case x #: xs => x #: Take[xs, n1]
36+
}
37+
}
38+
type Drop[T <: TupleK, N <: Int] <: TupleK = N match {
39+
case 0 => T
40+
case S[n1] => T match {
41+
case EmptyTupleK => EmptyTupleK
42+
case x #: xs => Drop[xs, n1]
43+
}
44+
}
45+
type Split[T <: TupleK, N <: Int] = (Take[T, N], Drop[T, N])
46+
}
47+
48+
type EmptyTupleK = EmptyTupleK.type
49+
50+
object EmptyTupleK extends TupleK
51+
52+
sealed trait NonEmptyTupleK extends TupleK
53+
sealed abstract class #:[+H, +T <: TupleK] extends NonEmptyTupleK

0 commit comments

Comments
 (0)