Skip to content

Commit d4df4b9

Browse files
Backport "Fix exception on sequence matching with drop" to 3.5.2 (#21483)
Backports #21281 to the 3.5.2 branch. PR submitted by the release tooling. [skip ci]
2 parents 1e0e136 + b093ae8 commit d4df4b9

File tree

2 files changed

+120
-2
lines changed

2 files changed

+120
-2
lines changed

Diff for: compiler/src/dotty/tools/dotc/transform/init/Objects.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -1485,12 +1485,12 @@ class Objects(using Context @constructorOnly):
14851485
if isWildcardStarArgList(pats) then
14861486
if pats.size == 1 then
14871487
// call .toSeq
1488-
val toSeqDenot = scrutineeType.member(nme.toSeq).suchThat(_.info.isParameterless)
1488+
val toSeqDenot = getMemberMethod(scrutineeType, nme.toSeq, toSeqType(elemType))
14891489
val toSeqRes = call(scrutinee, toSeqDenot.symbol, Nil, scrutineeType, superType = NoType, needResolve = true)
14901490
evalPattern(toSeqRes, pats.head)
14911491
else
14921492
// call .drop
1493-
val dropDenot = getMemberMethod(scrutineeType, nme.drop, applyType(elemType))
1493+
val dropDenot = getMemberMethod(scrutineeType, nme.drop, dropType(elemType))
14941494
val dropRes = call(scrutinee, dropDenot.symbol, ArgInfo(Bottom, summon[Trace], EmptyTree) :: Nil, scrutineeType, superType = NoType, needResolve = true)
14951495
for pat <- pats.init do evalPattern(applyRes, pat)
14961496
evalPattern(dropRes, pats.last)

Diff for: tests/init-global/pos/match-complete.scala

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
object Matcher {
2+
// Chained Match
3+
val chained_match_xs: List[Any] = List(1, 2, 3)
4+
val chained_match_x = chained_match_xs match {
5+
case Nil => "empty"
6+
case _ => "nonempty"
7+
} match {
8+
case "empty" => 0
9+
case "nonempty" => 1
10+
}
11+
println(chained_match_x)
12+
13+
// Vararg Splices
14+
val vararg_arr = Array(0, 1, 2, 3)
15+
val vararg_lst = List(vararg_arr*) // vararg splice argument
16+
// Throws an exception?
17+
val vararg_splice = vararg_lst match
18+
case List(0, 1, xs*) => 1 // binds xs to Seq(2, 3)
19+
case List(1, _*) => 0 // wildcard pattern
20+
case _ => 2
21+
println(vararg_splice)
22+
println(vararg_lst)
23+
24+
// Pattern Definitions
25+
val patter_def_xs: List[Any] = List(1, 2, 3)
26+
val (patter_def_x: Any) :: _ = patter_def_xs : @unchecked
27+
println(patter_def_x)
28+
29+
val patter_def_pair = (1, true)
30+
val (patter_def_a, patter_def_b) = patter_def_pair
31+
println(patter_def_a)
32+
33+
val elems: List[(Int, Int)] = List((1, 2), (3, 4), (5, 6))
34+
35+
for ((x,y) <- elems) do println(x)
36+
37+
def main(args: Array[String]) = {
38+
// println(chained_match_x)
39+
println(vararg_splice)
40+
// println(patter_def_x)
41+
// println(
42+
}
43+
}
44+
45+
46+
// Patter Matching Using Extractors
47+
48+
// Option Extractors
49+
case class Person(name: String, age: Int)
50+
object Person {
51+
def unapply(person: Person): Option[(String, Int)] = Some((person.name, person.age))
52+
}
53+
54+
object OptionMatcher {
55+
val person = Person("Alice", 25)
56+
57+
val result = person match {
58+
case Person(name, age) => s"Name: $name, Age: $age"
59+
case _ => "Not a person"
60+
}
61+
println(result)
62+
}
63+
64+
65+
66+
// Boolean Extractors
67+
object Adult {
68+
def unapply(person: Person): Boolean = person.age >= 18
69+
}
70+
71+
object BooleanMatcher {
72+
val person = Person("Charlie", 17)
73+
74+
val adultResult = person match {
75+
case Adult() => s"${person.name} is an adult"
76+
case _ => s"${person.name} is not an adult"
77+
}
78+
79+
println(adultResult)
80+
}
81+
82+
83+
84+
// Variadic Extractors
85+
// Add cases for exceptions
86+
//
87+
// Adding some warning test cases
88+
// -
89+
90+
object VariadicExtractor {
91+
// Define an unapply method that takes a List and returns an Option of Seq
92+
def unapplySeq[A](list: List[A]): Option[Seq[A]] = Some(list)
93+
}
94+
95+
object PatternMatchExample extends App {
96+
def describeList(list: List[Int]): String = list match {
97+
case VariadicExtractor(1, 2, rest @ _*) =>
98+
s"Starts with 1, 2 followed by: ${rest.mkString(", ")}"
99+
case VariadicExtractor(1, rest @ _*) =>
100+
s"Starts with 1 followed by: ${rest.mkString(", ")}"
101+
case VariadicExtractor(first, second, rest @ _*) =>
102+
s"Starts with $first, $second followed by: ${rest.mkString(", ")}"
103+
case VariadicExtractor(single) =>
104+
s"Only one element: $single"
105+
case VariadicExtractor() =>
106+
"Empty list"
107+
case _ =>
108+
"Unknown pattern"
109+
}
110+
111+
// Test cases
112+
println(describeList(List(1, 2, 3, 4, 5))) // Output: Starts with 1, 2 followed by: 3, 4, 5
113+
println(describeList(List(1, 3, 4, 5))) // Output: Starts with 1 followed by: 3, 4, 5
114+
println(describeList(List(2, 3, 4, 5))) // Output: Starts with 2, 3 followed by: 4, 5
115+
println(describeList(List(1))) // Output: Only one element: 1
116+
println(describeList(List())) // Output: Empty list
117+
}
118+

0 commit comments

Comments
 (0)