Skip to content

Commit 714f3b6

Browse files
authored
Fix regression: Prioritize tree type over proto type when typing Binds (#24175)
Fixes #24038 In the minimisation, the typer phase expanded ```scala case abcd: (h *: t, bh *: bt) => val (hh *: tt, bh *: bt) = abcd ``` into ```scala case abcd @ _:Tuple2[*:[h @ _, t @ _], *:[bh @ _, bt @ _]] => val $1$: (Any, Tuple, Any, Tuple) = abcd:((T, M[T]) & (h *: t, bh *: bt)) @unchecked match { case Tuple2.unapply[T, M[T]]( *:.unapply[Any, Tuple](hh @ _, tt @ _):(Any *: Tuple), *:.unapply[Any, Tuple](bh @ _, bt @ _):(Any *: Tuple)) => Tuple4.apply[Any, Tuple, Any, Tuple](hh, tt, bh, bt) } val hh: Any = $1$._1 val tt: Tuple = $1$._2 val bh: Any = $1$._3 val bt: Tuple = $1$._4 ``` Before the change in #23923 it would simplify `((T, M[T]) & (h *: t, bh *: bt))` into `(T & (h *: t), M[T] & (bh *: bt))` and thus generate: ```scala case abcd @ _:Tuple2[*:[h @ _, t @ _], *:[bh @ _, bt @ _]] => val $1$: (h, t, bh, bt) = abcd:(T & h *: t, M[T] & bh *: bt) @unchecked match { case Tuple2.unapply[T & h *: t, M[T] & bh *: bt]( *:.unapply[h, t](hh @ _, tt @ _), *:.unapply[bh, bt](bh @ _, bt @ _)) => Tuple4.apply[h, t, bh, bt](hh, tt, bh, bt) } val hh: h = $1$._1 val tt: t = $1$._2 val bh: bh = $1$._3 val bt: bt = $1$._4 ``` Since it looks like this simplification is now illegal, and the unapply generation for intersection types seems to prioritize the leftmost argument, to fix this we make sure that when typing Binds we prioritize the user-created `tree.tpe` and deprioritize the inferred proto type, which hopefully is enough.
2 parents 569ad50 + 901744a commit 714f3b6

File tree

6 files changed

+50
-7
lines changed

6 files changed

+50
-7
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2875,7 +2875,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28752875
// leave the original tuple type; don't mix with & TupleXXL which would only obscure things
28762876
pt
28772877
case _ =>
2878-
pt & body1.tpe
2878+
body1.tpe & pt
28792879
val sym = newPatternBoundSymbol(name, symTp, tree.span)
28802880
if (pt == defn.ImplicitScrutineeTypeRef || tree.mods.is(Given)) sym.setFlag(Given)
28812881
if (ctx.mode.is(Mode.InPatternAlternative))

tests/neg/i13780-1.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- [E007] Type Mismatch Error: tests/neg/i13780-1.scala:38:24 ----------------------------------------------------------
22
38 | case x: (h *: t) => x.head // error
33
| ^^^^^^
4-
| Found: Tuple.Head[VS & h *: t]
4+
| Found: Tuple.Head[h *: t & VS]
55
| Required: h
66
| Note that implicit conversions were not tried because the result of an implicit conversion
77
| must be more specific than h
@@ -13,8 +13,8 @@
1313
|
1414
| Note: a match type could not be fully reduced:
1515
|
16-
| trying to reduce Tuple.Head[VS & h *: t]
17-
| failed since selector VS & h *: t
16+
| trying to reduce Tuple.Head[h *: t & VS]
17+
| failed since selector h *: t & VS
1818
| does not uniquely determine parameter x in
1919
| case x *: _ => x
2020
| The computed bounds for the parameter are:

tests/neg/i24096.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- [E007] Type Mismatch Error: tests/neg/i24096.scala:8:31 -------------------------------------------------------------
22
8 | case r: Terminal[?] => r // error
33
| ^
4-
| Found: (r : Pull[F, O, Unit] & Pull.Terminal[_])
4+
| Found: (r : Pull.Terminal[_] & Pull[F, O, Unit])
55
| Required: Pull[F2, O2, Unit]
66
|
77
| where: F is a type in class StreamPullOps with bounds <: [_²] =>> Any

tests/pos/i24038a.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
final class MBufferLong:
2+
final def +=(elem: Long): this.type = ???
3+
4+
type M[Tup <: Tuple] <: Tuple = Tup match
5+
case EmptyTuple => EmptyTuple
6+
case h *: t => BufferOf[h] *: M[t]
7+
8+
type M2[T <: Tuple] <: Tuple = (T, M[T]) match
9+
case (h *: t, a *: b) => BufferOf[h] *: M2[t]
10+
case (EmptyTuple, EmptyTuple) => EmptyTuple
11+
case (_, EmptyTuple) => EmptyTuple
12+
case (EmptyTuple, _) => EmptyTuple
13+
14+
type BufferOf[T] = T match
15+
case Long => MBufferLong
16+
17+
inline def append[T](t: T, buffer: BufferOf[T]): BufferOf[T] =
18+
inline (t, buffer) match
19+
case (x: Long, y: BufferOf[Long]) => y.+=(x)
20+
buffer
21+
22+
transparent inline def appendBuffers[T <: Tuple](t: T, buffers: M[T]): M2[T] = {
23+
inline (t, buffers) match
24+
case abcd: ((h *: t), bh *: bt) =>
25+
val (hh *: tt, bh *: bt) = abcd
26+
val x: BufferOf[h] = append[h](hh, bh.asInstanceOf[BufferOf[h]])
27+
x *: appendBuffers[t](tt, bt.asInstanceOf[M[t]])
28+
case _: (EmptyTuple, EmptyTuple) => EmptyTuple
29+
case _: (_, EmptyTuple) => EmptyTuple
30+
case _: (EmptyTuple, _) => EmptyTuple
31+
}

tests/pos/i24038b.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
final class MBufferLong
2+
3+
type M[Tup <: Tuple] <: Tuple = Tup match
4+
case EmptyTuple => EmptyTuple
5+
case h *: t => MBufferLong *: M[t]
6+
7+
def appendBuffers[T <: Tuple](t: T, buffers: M[T]): Unit = {
8+
(t, buffers) match
9+
case abcd: (h *: t, bh *: bt) =>
10+
val (hh *: tt, bh *: bt) = abcd
11+
summon[hh.type <:< h]
12+
}

tests/semanticdb/metac.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4991,8 +4991,8 @@ _empty_/Txn# => trait Txn [typeparam T <: Txn[T]] extends Object { self: Txn[T]
49914991
_empty_/Txn#[T] => typeparam T <: Txn[T]
49924992
_empty_/Txn#`<init>`(). => primary ctor <init> [typeparam T <: Txn[T]](): Txn[T]
49934993
local0 => val local out: Repr[Out]
4994-
local1 => val local inObj: Repr[In] & Obj[In]
4995-
local2 => val local outObj: Repr[Out] & Obj[Out]
4994+
local1 => val local inObj: Obj[In] & Repr[In]
4995+
local2 => val local outObj: Obj[Out] & Repr[Out]
49964996

49974997
Occurrences:
49984998
[1:6..1:9): Txn <- _empty_/Txn#

0 commit comments

Comments
 (0)