Skip to content

Commit 0722bf4

Browse files
authored
Merge pull request #12924 from dotty-staging/fix-i12126
ProtoTypes#normalizedCompatible: keep more constraints
2 parents ecbe3d2 + dd8398d commit 0722bf4

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed

compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,8 @@ object ProtoTypes {
6464
i"""normalizedCompatible for $poly, $pt = $result
6565
|constraint was: ${ctx.typerState.constraint}
6666
|constraint now: ${newctx.typerState.constraint}""")
67-
if result
68-
&& (ctx.typerState.constraint ne newctx.typerState.constraint)
69-
&& {
70-
val existingVars = ctx.typerState.uninstVars.toSet
71-
newctx.typerState.uninstVars.forall(existingVars.contains)
72-
}
73-
then newctx.typerState.commit()
74-
// If the new constrait contains fresh type variables we cannot keep it,
75-
// since those type variables are not instantiated anywhere in the source.
76-
// See pos/i6682a.scala for a test case. See pos/11243.scala and pos/i5773b.scala
77-
// for tests where it matters that we keep the constraint otherwise.
78-
// TODO: A better solution would clean the new constraint, so that it "avoids"
79-
// the problematic type variables. But we have not implemented such an algorithm yet.
67+
if result && (ctx.typerState.constraint ne newctx.typerState.constraint) then
68+
newctx.typerState.commit()
8069
result
8170
case _ => testCompat
8271
else explore(testCompat)

tests/pos/i12126.scala

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
object Structures:
2+
3+
trait Functor[F[_]]:
4+
extension [A](fa: F[A])
5+
def map[B](f: A => B): F[B]
6+
def as[B](b: B): F[B] = map(_ => b)
7+
def void: F[Unit] = as(())
8+
9+
trait Applicative[F[_]] extends Functor[F]:
10+
def pure[A](a: A): F[A]
11+
def unit: F[Unit] = pure(())
12+
extension[A](fa: F[A])
13+
def map2[B, C](fb: F[B], f: (A, B) => C): F[C]
14+
def map[B](f: A => B): F[B] =
15+
fa.map2(unit, (a, _) => f(a))
16+
17+
trait Monad[F[_]] extends Applicative[F]:
18+
extension[A](fa: F[A])
19+
def flatMap[B](f: A => F[B]): F[B]
20+
override def map[B](f: A => B): F[B] =
21+
flatMap(a => pure(f(a)))
22+
def map2[B, C](fb: F[B], f: (A, B) => C): F[C] =
23+
flatMap(a => fb.map(b => f(a, b)))
24+
25+
given Monad[List] with
26+
def pure[A](a: A) = List(a)
27+
extension[A](fa: List[A])
28+
def flatMap[B](f: A => List[B]) = fa.flatMap(f)
29+
30+
given Monad[Option] with
31+
def pure[A](a: A) = Some(a)
32+
extension[A](fa: Option[A])
33+
def flatMap[B](f: A => Option[B]) = fa.flatMap(f)
34+
35+
36+
opaque type Kleisli[F[_], A, B] = A => F[B]
37+
38+
extension [F[_], A, B](k: Kleisli[F, A, B])
39+
def apply(a: A): F[B] = k(a)
40+
41+
object Kleisli:
42+
def apply[F[_], A, B](f: A => F[B]): Kleisli[F, A, B] = f
43+
44+
given [F[_], A](using F: Monad[F]): Monad[[B] =>> Kleisli[F, A, B]] with
45+
def pure[B](b: B) = Kleisli(_ => F.pure(b))
46+
extension[B](k: Kleisli[F, A, B])
47+
def flatMap[C](f: B => Kleisli[F, A, C]) =
48+
a => k(a).flatMap(b => f(b)(a))
49+
50+
end Structures
51+
52+
@main def run =
53+
import Structures.{*, given}
54+
println(List(1, 2, 3).map2(List(4, 5, 6), (_, _)))
55+
56+
val p: Kleisli[Option, Int, Int] = Kleisli((x: Int) => if x % 2 == 0 then Some(x) else None)
57+
val q: Kleisli[Option, Int, Int] = summon[Applicative[[B] =>> Kleisli[Option, Int, B]]].pure(20)
58+
println(p.map2(q, _ + _)(42))
59+

0 commit comments

Comments
 (0)