Skip to content

Fix problem involving classtag based pattern matches. #1187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val proto2 = // the computed type of the `elemtpt` field
if (!tree.elemtpt.isEmpty) WildcardType
else if (isFullyDefined(proto1, ForceDegree.none)) proto1
else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]])
else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]])
defn.ObjectType // generic empty Java varargs are of type Object[]
else ctx.typeComparer.lub(elems1.tpes)
val elemtpt1 = typed(tree.elemtpt, proto2)
Expand Down Expand Up @@ -961,13 +961,23 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
assignType(cpy.TypeBoundsTree(tree)(lo1, hi1), lo1, hi1)
}

def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = track("typedBind") {
def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = track("typedBind") {
val pt1 = fullyDefinedType(pt, "pattern variable", tree.pos)
val body1 = typed(tree.body, pt1)
typr.println(i"typed bind $tree pt = $pt1 bodytpe = ${body1.tpe}")
val flags = if (tree.isType) BindDefinedType else EmptyFlags
val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos)
assignType(cpy.Bind(tree)(tree.name, body1), sym)
body1 match {
case UnApply(fn, Nil, arg :: Nil) if tree.body.isInstanceOf[untpd.Typed] =>
// A typed pattern `x @ (_: T)` with an implicit `ctag: ClassTag[T]`
// was rewritten to `x @ ctag(_)`.
// Rewrite further to `ctag(x @ _)`
assert(fn.symbol.owner == defn.ClassTagClass)
tpd.cpy.UnApply(body1)(fn, Nil,
typed(untpd.Bind(tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil)
case _ =>
val flags = if (tree.isType) BindDefinedType else EmptyFlags
val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos)
assignType(cpy.Bind(tree)(tree.name, body1), sym)
}
}

def typedAlternative(tree: untpd.Alternative, pt: Type)(implicit ctx: Context): Alternative = track("typedAlternative") {
Expand Down
19 changes: 19 additions & 0 deletions tests/pos/i1174.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import scala.reflect.ClassTag
import scala.util._

object Main {
class A

def constructAs[TTT <: A](implicit ev: ClassTag[TTT]): Try[TTT] = Try {
new A()
}.flatMap {
case ev(inst) =>
val b: TTT = inst
Success(inst)
case inst: TTT =>
Success(inst)
case _ =>
val tag = implicitly[ClassTag[TTT]]
Failure(new ClassCastException(s"Failed to construct instance of class ${tag.runtimeClass.getName}"))
}
}