Skip to content

Commit e96c20f

Browse files
committed
Support transparent matches with simple typed patterns
More work on pattern matching still to be done.
1 parent a125c67 commit e96c20f

File tree

14 files changed

+325
-76
lines changed

14 files changed

+325
-76
lines changed

compiler/src/dotty/tools/dotc/config/Config.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ object Config {
160160
final val showCompletions = false
161161

162162
/** If set, enables tracing */
163-
final val tracingEnabled = false
163+
final val tracingEnabled = true
164164

165165
/** Initial capacity of uniques HashMap.
166166
* Note: This MUST BE a power of two to work with util.HashSet

compiler/src/dotty/tools/dotc/core/NameKinds.scala

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -275,23 +275,25 @@ object NameKinds {
275275
}
276276

277277
/** Other unique names */
278-
val TempResultName = new UniqueNameKind("ev$")
279-
val EvidenceParamName = new UniqueNameKind("evidence$")
280-
val DepParamName = new UniqueNameKind("(param)")
281-
val LazyImplicitName = new UniqueNameKind("$_lazy_implicit_$")
282-
val LazyLocalName = new UniqueNameKind("$lzy")
283-
val LazyLocalInitName = new UniqueNameKind("$lzyINIT")
284-
val LazyFieldOffsetName = new UniqueNameKind("$OFFSET")
285-
val LazyBitMapName = new UniqueNameKind(nme.BITMAP_PREFIX.toString)
286-
val NonLocalReturnKeyName = new UniqueNameKind("nonLocalReturnKey")
287-
val WildcardParamName = new UniqueNameKind("_$")
288-
val TailLabelName = new UniqueNameKind("tailLabel")
289-
val ExceptionBinderName = new UniqueNameKind("ex")
290-
val SkolemName = new UniqueNameKind("?")
291-
val LiftedTreeName = new UniqueNameKind("liftedTree")
292-
val SuperArgName = new UniqueNameKind("$superArg$")
293-
val DocArtifactName = new UniqueNameKind("$doc")
294-
val UniqueInlineName = new UniqueNameKind("$i")
278+
val TempResultName = new UniqueNameKind("ev$")
279+
val EvidenceParamName = new UniqueNameKind("evidence$")
280+
val DepParamName = new UniqueNameKind("(param)")
281+
val LazyImplicitName = new UniqueNameKind("$_lazy_implicit_$")
282+
val LazyLocalName = new UniqueNameKind("$lzy")
283+
val LazyLocalInitName = new UniqueNameKind("$lzyINIT")
284+
val LazyFieldOffsetName = new UniqueNameKind("$OFFSET")
285+
val LazyBitMapName = new UniqueNameKind(nme.BITMAP_PREFIX.toString)
286+
val NonLocalReturnKeyName = new UniqueNameKind("nonLocalReturnKey")
287+
val WildcardParamName = new UniqueNameKind("_$")
288+
val TailLabelName = new UniqueNameKind("tailLabel")
289+
val ExceptionBinderName = new UniqueNameKind("ex")
290+
val SkolemName = new UniqueNameKind("?")
291+
val LiftedTreeName = new UniqueNameKind("liftedTree")
292+
val SuperArgName = new UniqueNameKind("$superArg$")
293+
val DocArtifactName = new UniqueNameKind("$doc")
294+
val UniqueInlineName = new UniqueNameKind("$i")
295+
val TransparentScrutineeName = new UniqueNameKind("$scrutinee")
296+
val TransparentBinderName = new UniqueNameKind("$elem")
295297

296298
/** A kind of unique extension methods; Unlike other unique names, these can be
297299
* unmangled.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ object Inferencing {
185185
*
186186
* Invariant refinement can be assumed if `PatternType`'s class(es) are final or
187187
* case classes (because of `RefChecks#checkCaseClassInheritanceInvariant`).
188+
*
189+
* TODO: Update so that GADT symbols can be variant, and we special case final class types in patterns
188190
*/
189191
def constrainPatternType(tp: Type, pt: Type)(implicit ctx: Context): Boolean = {
190192
def refinementIsInvariant(tp: Type): Boolean = tp match {

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

Lines changed: 185 additions & 36 deletions
Large diffs are not rendered by default.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ object PrepareTransparent {
290290

291291
def traverse(tree: Tree)(implicit ctx: Context): Unit = {
292292
tree match {
293+
case Ident(nme.WILDCARD) =>
293294
case _: Ident | _: This =>
294295
//println(i"leaf: $tree at ${tree.pos}")
295296
if (tree.symbol.exists && !isLocal(tree.symbol, inlineMethod)) {

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ class Typer extends Namer
966966
assignType(cpy.Closure(tree)(env1, meth1, target), meth1, target)
967967
}
968968

969-
def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context) = track("typedMatch") {
969+
def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context): Tree = track("typedMatch") {
970970
tree.selector match {
971971
case EmptyTree =>
972972
val (protoFormals, _) = decomposeProtoFunction(pt, 1)
@@ -975,13 +975,17 @@ class Typer extends Namer
975975
case _ =>
976976
val sel1 = typedExpr(tree.selector)
977977
val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos).widen
978-
979-
val cases1 = harmonic(harmonize)(typedCases(tree.cases, selType, pt.notApplied))
980-
.asInstanceOf[List[CaseDef]]
981-
assignType(cpy.Match(tree)(sel1, cases1), cases1)
978+
typedMatchFinish(tree, sel1, selType, pt)
982979
}
983980
}
984981

982+
// Overridden in InlineTyper for transparent matches
983+
def typedMatchFinish(tree: untpd.Match, sel: Tree, selType: Type, pt: Type)(implicit ctx: Context): Tree = {
984+
val cases1 = harmonic(harmonize)(typedCases(tree.cases, selType, pt.notApplied))
985+
.asInstanceOf[List[CaseDef]]
986+
assignType(cpy.Match(tree)(sel, cases1), cases1)
987+
}
988+
985989
def typedCases(cases: List[untpd.CaseDef], selType: Type, pt: Type)(implicit ctx: Context) = {
986990

987991
/** gadtSyms = "all type parameters of enclosing methods that appear
@@ -1004,7 +1008,7 @@ class Typer extends Namer
10041008
accu(Set.empty, selType)
10051009
}
10061010

1007-
cases mapconserve (typedCase(_, pt, selType, gadtSyms))
1011+
cases.mapconserve(typedCase(_, pt, selType, gadtSyms))
10081012
}
10091013

10101014
/** Type a case. */

library/src/dotty/DottyPredef.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ object DottyPredef {
3434
assertFail()
3535
}
3636

37-
final def assertFail(): Unit = throw new java.lang.AssertionError("assertion failed")
38-
final def assertFail(message: => Any): Unit = throw new java.lang.AssertionError("assertion failed: " + message)
37+
def assertFail(): Unit = throw new java.lang.AssertionError("assertion failed")
38+
def assertFail(message: => Any): Unit = throw new java.lang.AssertionError("assertion failed: " + message)
3939

4040
@forceInline final def implicitly[T](implicit ev: T): T = ev
41+
42+
@forceInline def locally[T](body: => T): T = body
4143
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
object Test {
3+
def anyValue[T]: T = ???
4+
5+
transparent def test[T] = anyValue[T] match { // error
6+
case _: Byte =>
7+
case _: Char =>
8+
}
9+
10+
test[String]
11+
}

tests/neg/typelevel.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,13 @@ object Test {
5555
class Deco2(val as: HList) extends java.lang.Cloneable with java.lang.Comparable[Deco2] {
5656
transparent def ++ (bs: HList) = concat(as, bs)
5757
}
58+
59+
def anyValue[T]: T = ???
60+
61+
transparent def test[T] = anyValue[T] match {
62+
case _: Byte =>
63+
case _: Char =>
64+
}
65+
66+
test[String]
5867
}

tests/pos/i3050.scala

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
11
object Test {
2+
trait Option[+T]
3+
case object None extends Option[Nothing]
4+
case class Some[+T](x: T) extends Option[T]
5+
26
transparent def openImpl(): Int =
37
Some(42) match { case Some(i) => i }
48

5-
def open(): Int = openImpl()
9+
def open() = openImpl()
10+
11+
transparent def openImpl1(): Int =
12+
new Some(42) match { case Some(i) => i }
13+
14+
def open1() = openImpl1()
615

716
transparent def openImpl2(): Int =
8-
Some(42) match { case None => 42 }
17+
None match { case None => 42 }
918

1019
def open2(): Int = openImpl2()
1120
}
21+
22+
// Same as Test, with Scala2 case classes
23+
object Test2 {
24+
transparent def openImpl(): Int =
25+
Some(42) match { case Some(i) => i }
26+
27+
def open() = openImpl()
28+
29+
transparent def openImpl1(): Int =
30+
new Some(42) match { case Some(i) => i }
31+
32+
def open1() = openImpl1()
33+
34+
transparent def openImpl2(): Int =
35+
None match { case None => 42 }
36+
37+
def open2(): Int = openImpl2()
38+
39+
}

0 commit comments

Comments
 (0)