Skip to content

Commit fadcf44

Browse files
committed
Merge pull request #1187 from dotty-staging/fix-#1174
Fix problem involving classtag based pattern matches.
2 parents 1b29119 + 4df2e28 commit fadcf44

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
842842
val proto2 = // the computed type of the `elemtpt` field
843843
if (!tree.elemtpt.isEmpty) WildcardType
844844
else if (isFullyDefined(proto1, ForceDegree.none)) proto1
845-
else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]])
845+
else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]])
846846
defn.ObjectType // generic empty Java varargs are of type Object[]
847847
else ctx.typeComparer.lub(elems1.tpes)
848848
val elemtpt1 = typed(tree.elemtpt, proto2)
@@ -961,13 +961,23 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
961961
assignType(cpy.TypeBoundsTree(tree)(lo1, hi1), lo1, hi1)
962962
}
963963

964-
def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = track("typedBind") {
964+
def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = track("typedBind") {
965965
val pt1 = fullyDefinedType(pt, "pattern variable", tree.pos)
966966
val body1 = typed(tree.body, pt1)
967967
typr.println(i"typed bind $tree pt = $pt1 bodytpe = ${body1.tpe}")
968-
val flags = if (tree.isType) BindDefinedType else EmptyFlags
969-
val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos)
970-
assignType(cpy.Bind(tree)(tree.name, body1), sym)
968+
body1 match {
969+
case UnApply(fn, Nil, arg :: Nil) if tree.body.isInstanceOf[untpd.Typed] =>
970+
// A typed pattern `x @ (_: T)` with an implicit `ctag: ClassTag[T]`
971+
// was rewritten to `x @ ctag(_)`.
972+
// Rewrite further to `ctag(x @ _)`
973+
assert(fn.symbol.owner == defn.ClassTagClass)
974+
tpd.cpy.UnApply(body1)(fn, Nil,
975+
typed(untpd.Bind(tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil)
976+
case _ =>
977+
val flags = if (tree.isType) BindDefinedType else EmptyFlags
978+
val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos)
979+
assignType(cpy.Bind(tree)(tree.name, body1), sym)
980+
}
971981
}
972982

973983
def typedAlternative(tree: untpd.Alternative, pt: Type)(implicit ctx: Context): Alternative = track("typedAlternative") {

tests/pos/i1174.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import scala.reflect.ClassTag
2+
import scala.util._
3+
4+
object Main {
5+
class A
6+
7+
def constructAs[TTT <: A](implicit ev: ClassTag[TTT]): Try[TTT] = Try {
8+
new A()
9+
}.flatMap {
10+
case ev(inst) =>
11+
val b: TTT = inst
12+
Success(inst)
13+
case inst: TTT =>
14+
Success(inst)
15+
case _ =>
16+
val tag = implicitly[ClassTag[TTT]]
17+
Failure(new ClassCastException(s"Failed to construct instance of class ${tag.runtimeClass.getName}"))
18+
}
19+
}

0 commit comments

Comments
 (0)