Skip to content

Commit 6a0fc8c

Browse files
committed
Cleanup + Documentation + More neg tests
1 parent 4d00b92 commit 6a0fc8c

File tree

3 files changed

+47
-30
lines changed

3 files changed

+47
-30
lines changed

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

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,37 @@ object Applications {
100100
Nil
101101
}
102102

103+
/** If `getType` is of the form:
104+
* ```
105+
* {
106+
* def lengthCompare(len: Int): Int // or, def length: Int
107+
* def apply(i: Int): T = a(i)
108+
* def drop(n: Int): scala.Seq[T]
109+
* def toSeq: scala.Seq[T]
110+
* }
111+
* ```
112+
* returns `T`, otherwise NoType.
113+
*/
103114
def unapplySeqTypeElemTp(getTp: Type): Type = {
104-
val lengthTp = ExprType(defn.IntType)
105-
val lengthCompareTp = MethodType(List("len".toTermName))(_ => defn.IntType :: Nil, _ => defn.IntType)
106-
def applyTp(elemTp: Type) = MethodType(List("i".toTermName))(_ => defn.IntType :: Nil, _ => elemTp)
107-
def dropTp(elemTp: Type) = MethodType(List("n".toTermName))(_ => defn.IntType :: Nil, _ => defn.SeqType.appliedTo(elemTp))
115+
def lengthTp = ExprType(defn.IntType)
116+
def lengthCompareTp = MethodType(List(defn.IntType), defn.IntType)
117+
def applyTp(elemTp: Type) = MethodType(List(defn.IntType), elemTp)
118+
def dropTp(elemTp: Type) = MethodType(List(defn.IntType), defn.SeqType.appliedTo(elemTp))
108119
def toSeqTp(elemTp: Type) = ExprType(defn.SeqType.appliedTo(elemTp))
109120

121+
// the result type of `def apply(i: Int): T`
110122
val elemTp = getTp.member(nme.apply).suchThat(_.info <:< applyTp(WildcardType)).info.resultType
111123

112-
def test(name: Name, tp: Type) = getTp.member(name).suchThat(getTp.memberInfo(_) <:< tp).exists
124+
def hasMethod(name: Name, tp: Type) =
125+
getTp.member(name).suchThat(getTp.memberInfo(_) <:< tp).exists
113126

114-
val valid =
127+
val isValid =
115128
elemTp.exists &&
116-
(test(nme.lengthCompare, lengthCompareTp) ||
117-
test(nme.length, lengthTp)) &&
118-
test(nme.drop, dropTp(elemTp)) &&
119-
test(nme.toSeq, toSeqTp(elemTp))
129+
(hasMethod(nme.lengthCompare, lengthCompareTp) || hasMethod(nme.length, lengthTp)) &&
130+
hasMethod(nme.drop, dropTp(elemTp)) &&
131+
hasMethod(nme.toSeq, toSeqTp(elemTp))
120132

121-
if (valid) elemTp else NoType
133+
if (isValid) elemTp else NoType
122134
}
123135

124136
if (unapplyName == nme.unapplySeq) {

docs/docs/reference/changed/pattern-matching.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,12 @@ object FirstChars {
6767

6868
- Extractor defines `def unapplySeq(x: T): U`
6969
- `U` has (parameterless `def` or `val`) members `isEmpty: Boolean` and `get: S`
70-
- `S` conforms to `X` or `Y`, `T2` and `T3` conform to `T1`
70+
- `S` conforms to `X`, `T2` and `T3` conform to `T1`
7171

7272
```Scala
7373
type X = {
74-
def lengthCompare(len: Int): Int
75-
def apply(i: Int): T1 = a(i)
76-
def drop(n: Int): scala.Seq[T2]
77-
def toSeq: scala.Seq[T3]
78-
}
79-
80-
type Y = {
81-
def length: Int
82-
def apply(i: Int): T1 = a(i)
74+
def lengthCompare(len: Int): Int // or, `def length: Int`
75+
def apply(i: Int): T1
8376
def drop(n: Int): scala.Seq[T2]
8477
def toSeq: scala.Seq[T3]
8578
}

tests/neg/i4984.scala

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
11
object Array2 {
22
def unapplySeq(x: Array[Int]): Data = new Data
3-
4-
final class Data {
3+
class Data {
54
def isEmpty: Boolean = false
65
def get: Data = this
76
def lengthCompare(len: Int): Int = 0
87
def apply(i: Int): Int = 3
8+
// drop return type, not conforming to apply's
99
def drop(n: Int): scala.Seq[String] = Seq("hello")
1010
def toSeq: scala.Seq[Int] = Seq(6, 7)
1111
}
1212
}
1313

14-
object Test {
15-
def test1(xs: Array[Int]): Int = xs match {
16-
case Array2(x, y) => x + y // error // error
14+
object Array3 {
15+
def unapplySeq(x: Array[Int]): Data = new Data
16+
class Data {
17+
def isEmpty: Boolean = false
18+
def get: Data = this
19+
def lengthCompare(len: Int): Int = 0
20+
// missing apply
21+
def drop(n: Int): scala.Seq[Int] = ???
22+
def toSeq: scala.Seq[Int] = ???
1723
}
24+
}
1825

19-
def test2(xs: Array[Int]): Seq[Int] = xs match {
20-
case Array2(x, y, xs:_*) => xs // error
26+
object Test {
27+
def test(xs: Array[Int]): Int = xs match {
28+
case Array2(x, y) => 1 // error
29+
case Array2(x, y, xs: _*) => 2 // error
30+
case Array2(xs: _*) => 3 // error
2131
}
2232

23-
def test3(xs: Array[Int]): Seq[Int] = xs match {
24-
case Array2(xs:_*) => xs // error
33+
def test2(xs: Array[Int]): Int = xs match {
34+
case Array3(x, y) => 1 // error
35+
case Array3(x, y, xs: _*) => 2 // error
36+
case Array3(xs: _*) => 3 // error
2537
}
2638
}

0 commit comments

Comments
 (0)