Browse files

unapply may be called on arbitrary tree

before, an unapply call would be derived from a case SomeClass(_, ..., _) pattern,
where SomeClass is a valid constructor reference, and thus also a reference to an
unapply-bearing companion object

this assumption is going to be violated once we start using class tags to make
uncheckable type tests checkable, since we could encounter unapply calls like
{<method calls that construct classTag>}.unapply(<arg>)
  • Loading branch information...
adriaanm authored and xeno-by committed Jun 4, 2012
1 parent ef9720f commit b31c6d4f778df6b415c605a468b155cea0b84a16
Showing with 13 additions and 4 deletions.
  1. +13 −4 src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -966,12 +966,21 @@ trait Typers extends Modes with Adaptations with Tags {
* see test/files/../t5189*.scala
def adaptConstrPattern(): Tree = { // (5)
- def isExtractor(sym: Symbol) = reallyExists(unapplyMember(sym.tpe))
- val extractor = tree.symbol filter isExtractor
+ def hasUnapplyMember(tp: Type) = reallyExists(unapplyMember(tp))
+ val overloadedExtractorOfObject = tree.symbol filter (sym => hasUnapplyMember(sym.tpe))
+ // if the tree's symbol's type does not define an extractor, maybe the tree's type does
+ // this is the case when we encounter an arbitrary tree as the target of an unapply call (rather than something that looks like a constructor call)
+ // (for now, this only happens due to maybeTypeTagExtractor, but when we support parameterized extractors, it will become more common place)
+ val extractor = overloadedExtractorOfObject orElse unapplyMember(tree.tpe)
if (extractor != NoSymbol) {
- tree setSymbol extractor
+ // if we did some ad-hoc overloading resolution, update the tree's symbol
+ // do not update the symbol if the tree's symbol's type does not define an unapply member
+ // (e.g. since it's some method that returns an object with an unapply member)
+ if (overloadedExtractorOfObject != NoSymbol)
+ tree setSymbol overloadedExtractorOfObject
tree.tpe match {
- case OverloadedType(pre, alts) => tree.tpe = overloadedType(pre, alts filter isExtractor)
+ case OverloadedType(pre, alts) => tree.tpe = overloadedType(pre, alts filter (alt => hasUnapplyMember(alt.tpe)))
case _ =>
val unapply = unapplyMember(extractor.tpe)

0 comments on commit b31c6d4

Please sign in to comment.