From f5a26d7a12296ca37e67fc5c31fbfa48d0f3e430 Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Mon, 13 Oct 2025 15:17:30 +0200 Subject: [PATCH 1/2] Prioritise tree type over proto type when typing Binds [Cherry-picked 5c9c31cd564b7a3010f32699f350d7bdce8bdef7] --- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- tests/pos/i24038a.scala | 31 +++++++++++++++++++ tests/pos/i24038b.scala | 12 +++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i24038a.scala create mode 100644 tests/pos/i24038b.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index fc71c0e43034..815c88ceb465 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2875,7 +2875,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // leave the original tuple type; don't mix with & TupleXXL which would only obscure things pt case _ => - pt & body1.tpe + body1.tpe & pt val sym = newPatternBoundSymbol(name, symTp, tree.span) if (pt == defn.ImplicitScrutineeTypeRef || tree.mods.is(Given)) sym.setFlag(Given) if (ctx.mode.is(Mode.InPatternAlternative)) diff --git a/tests/pos/i24038a.scala b/tests/pos/i24038a.scala new file mode 100644 index 000000000000..9386e7d98751 --- /dev/null +++ b/tests/pos/i24038a.scala @@ -0,0 +1,31 @@ +final class MBufferLong: + final def +=(elem: Long): this.type = ??? + +type M[Tup <: Tuple] <: Tuple = Tup match + case EmptyTuple => EmptyTuple + case h *: t => BufferOf[h] *: M[t] + +type M2[T <: Tuple] <: Tuple = (T, M[T]) match + case (h *: t, a *: b) => BufferOf[h] *: M2[t] + case (EmptyTuple, EmptyTuple) => EmptyTuple + case (_, EmptyTuple) => EmptyTuple + case (EmptyTuple, _) => EmptyTuple + +type BufferOf[T] = T match + case Long => MBufferLong + +inline def append[T](t: T, buffer: BufferOf[T]): BufferOf[T] = + inline (t, buffer) match + case (x: Long, y: BufferOf[Long]) => y.+=(x) + buffer + +transparent inline def appendBuffers[T <: Tuple](t: T, buffers: M[T]): M2[T] = { + inline (t, buffers) match + case abcd: ((h *: t), bh *: bt) => + val (hh *: tt, bh *: bt) = abcd + val x: BufferOf[h] = append[h](hh, bh.asInstanceOf[BufferOf[h]]) + x *: appendBuffers[t](tt, bt.asInstanceOf[M[t]]) + case _: (EmptyTuple, EmptyTuple) => EmptyTuple + case _: (_, EmptyTuple) => EmptyTuple + case _: (EmptyTuple, _) => EmptyTuple +} diff --git a/tests/pos/i24038b.scala b/tests/pos/i24038b.scala new file mode 100644 index 000000000000..ec0d12a4689b --- /dev/null +++ b/tests/pos/i24038b.scala @@ -0,0 +1,12 @@ +final class MBufferLong + +type M[Tup <: Tuple] <: Tuple = Tup match + case EmptyTuple => EmptyTuple + case h *: t => MBufferLong *: M[t] + +def appendBuffers[T <: Tuple](t: T, buffers: M[T]): Unit = { + (t, buffers) match + case abcd: (h *: t, bh *: bt) => + val (hh *: tt, bh *: bt) = abcd + summon[hh.type <:< h] +} From 966f1d948d2b9d6290ca270dd7327667c99840d2 Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Mon, 13 Oct 2025 18:53:26 +0200 Subject: [PATCH 2/2] Fix .check tests [Cherry-picked 901744ad9827f36713777bb6017032e7ce797d07] --- tests/neg/i13780-1.check | 6 +++--- tests/neg/i24096.check | 2 +- tests/semanticdb/metac.expect | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/neg/i13780-1.check b/tests/neg/i13780-1.check index faf07be1b361..ab215337a7ed 100644 --- a/tests/neg/i13780-1.check +++ b/tests/neg/i13780-1.check @@ -1,7 +1,7 @@ -- [E007] Type Mismatch Error: tests/neg/i13780-1.scala:38:24 ---------------------------------------------------------- 38 | case x: (h *: t) => x.head // error | ^^^^^^ - | Found: Tuple.Head[VS & h *: t] + | Found: Tuple.Head[h *: t & VS] | Required: h | Note that implicit conversions were not tried because the result of an implicit conversion | must be more specific than h @@ -13,8 +13,8 @@ | | Note: a match type could not be fully reduced: | - | trying to reduce Tuple.Head[VS & h *: t] - | failed since selector VS & h *: t + | trying to reduce Tuple.Head[h *: t & VS] + | failed since selector h *: t & VS | does not uniquely determine parameter x in | case x *: _ => x | The computed bounds for the parameter are: diff --git a/tests/neg/i24096.check b/tests/neg/i24096.check index d46e1224a5df..0272747fd00e 100644 --- a/tests/neg/i24096.check +++ b/tests/neg/i24096.check @@ -1,7 +1,7 @@ -- [E007] Type Mismatch Error: tests/neg/i24096.scala:8:31 ------------------------------------------------------------- 8 | case r: Terminal[?] => r // error | ^ - | Found: (r : Pull[F, O, Unit] & Pull.Terminal[_]) + | Found: (r : Pull.Terminal[_] & Pull[F, O, Unit]) | Required: Pull[F2, O2, Unit] | | where: F is a type in class StreamPullOps with bounds <: [_²] =>> Any diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index a2e46a9ed131..db6d2e640f63 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -4991,8 +4991,8 @@ _empty_/Txn# => trait Txn [typeparam T <: Txn[T]] extends Object { self: Txn[T] _empty_/Txn#[T] => typeparam T <: Txn[T] _empty_/Txn#``(). => primary ctor [typeparam T <: Txn[T]](): Txn[T] local0 => val local out: Repr[Out] -local1 => val local inObj: Repr[In] & Obj[In] -local2 => val local outObj: Repr[Out] & Obj[Out] +local1 => val local inObj: Obj[In] & Repr[In] +local2 => val local outObj: Obj[Out] & Repr[Out] Occurrences: [1:6..1:9): Txn <- _empty_/Txn#