diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 97b4f73cfdec..ab6303acd821 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -366,13 +366,28 @@ trait ConstraintHandling { if (tpw eq tp) || dropped.forall(_ frozen_<:< tpw) then tp else tpw end dropTransparentTraits + /** If `tp` is an applied match type alias which is also an unreducible application + * of a higher-kinded type to a wildcard argument, widen to the match type's bound, + * in order to avoid an unreducible application of higher-kinded type ... in inferred type" + * error in PostTyper. Fixes #11246. + */ + def widenIrreducible(tp: Type)(using Context): Type = tp match + case tp @ AppliedType(tycon, _) if tycon.isLambdaSub && tp.hasWildcardArg => + tp.superType match + case MatchType(bound, _, _) => bound + case _ => tp + case _ => + tp + /** Widen inferred type `inst` with upper `bound`, according to the following rules: * 1. If `inst` is a singleton type, or a union containing some singleton types, - * widen (all) the singleton type(s), provided the result is a subtype of `bound` + * widen (all) the singleton type(s), provided the result is a subtype of `bound`. * (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint) * 2. If `inst` is a union type, approximate the union type from above by an intersection * of all common base types, provided the result is a subtype of `bound`. - * 3. drop transparent traits from intersections (see @dropTransparentTraits) + * 3. Widen some irreducible applications of higher-kinded types to wildcard arguments + * (see @widenIrreducible). + * 4. Drop transparent traits from intersections (see @dropTransparentTraits). * * Don't do these widenings if `bound` is a subtype of `scala.Singleton`. * Also, if the result of these widenings is a TypeRef to a module class, @@ -397,7 +412,7 @@ trait ConstraintHandling { val wideInst = if isSingleton(bound) then inst - else dropTransparentTraits(widenOr(widenSingle(inst)), bound) + else dropTransparentTraits(widenIrreducible(widenOr(widenSingle(inst))), bound) wideInst match case wideInst: TypeRef if wideInst.symbol.is(Module) => TermRef(wideInst.prefix, wideInst.symbol.sourceModule) diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index c3630d3bc047..547a48d99b79 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -33,6 +33,7 @@ i7872.scala 6709.scala 6687.scala i11236.scala +i11247.scala # Opaque type i5720.scala diff --git a/tests/pos/i11247.scala b/tests/pos/i11247.scala new file mode 100644 index 000000000000..bf3f9c3bd393 --- /dev/null +++ b/tests/pos/i11247.scala @@ -0,0 +1,53 @@ +import annotation.showAsInfix +import scala.compiletime._ + +class TupleKOps { + + + def tupleMerge(tuple1: TupleK, tuple2: TupleK): TupleK = ??? + + def tupleMergeSort(tuple: TupleK): TupleK = + if (tuple.size <= 1) tuple + else { + val (tuple1, tuple2) = tuple.splitAt(tuple.size / 2) + // val (tuple1: TupleK, tuple2: TupleK) = tuple.splitAt(tuple.size / 2) // ok + val (sorted1, sorted2) = (tupleMergeSort(tuple1), tupleMergeSort(tuple2)) + tupleMerge(sorted1, sorted2) + } + +} + +sealed trait TupleK { + import TupleK._ + /*inline*/ def size[This >: this.type <: TupleK]: Size[This] = ??? + /*inline*/ def splitAt[This >: this.type <: TupleK](n: Int): Split[This, n.type] = ??? +} + +object TupleK { + type Size[X <: TupleK] <: Int = X match { + case EmptyTupleK => 0 + case x #: xs => S[Size[xs]] + } + type Take[T <: TupleK, N <: Int] <: TupleK = N match { + case 0 => EmptyTupleK + case S[n1] => T match { + case EmptyTupleK => EmptyTupleK + case x #: xs => x #: Take[xs, n1] + } + } + type Drop[T <: TupleK, N <: Int] <: TupleK = N match { + case 0 => T + case S[n1] => T match { + case EmptyTupleK => EmptyTupleK + case x #: xs => Drop[xs, n1] + } + } + type Split[T <: TupleK, N <: Int] = (Take[T, N], Drop[T, N]) +} + +type EmptyTupleK = EmptyTupleK.type + +object EmptyTupleK extends TupleK + +sealed trait NonEmptyTupleK extends TupleK +sealed abstract class #:[+H, +T <: TupleK] extends NonEmptyTupleK \ No newline at end of file