Skip to content

Commit

Permalink
SI-6624 set info of case pattern binder to help find case field acces…
Browse files Browse the repository at this point in the history
…sors

sometimes the type checker infers a weird type for a sub-pattern of a case class/extractor pattern
this confuses the pattern matcher and it can't find the case field accessors for the sub-pattern

use the expected argument type of the extractor corresponding to the case class that we're matching
as the info for the sub-pattern binder -- this type more readily admits querying its caseFieldAccessors
  • Loading branch information
adriaanm committed Nov 17, 2012
1 parent ea87ecb commit 32c5732
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
Expand Up @@ -417,7 +417,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// (the prefix of the argument passed to the unapply must equal the prefix of the type of the binder)
val treeMaker = TypeTestTreeMaker(patBinder, patBinder, extractor.paramType, extractor.paramType)(pos, extractorArgTypeTest = true)
(List(treeMaker), treeMaker.nextBinder)
} else (Nil, patBinder)
} else {
// no type test needed, but the tree maker relies on `patBinderOrCasted` having type `extractor.paramType` (and not just some type compatible with it)
// SI-6624 shows this is necessary because apparently patBinder may have an unfortunate type (.decls don't have the case field accessors)
// TODO: get to the bottom of this -- I assume it happens when type checking infers a weird type for an unapply call
// by going back to the parameterType for the extractor call we get a saner type, so let's just do that for now
/* TODO: uncomment when `settings.developer` and `devWarning` become available
if (settings.developer.value && !(patBinder.info =:= extractor.paramType))
devWarning(s"resetting info of $patBinder: ${patBinder.info} to ${extractor.paramType}")
*/
(Nil, patBinder setInfo extractor.paramType)
}

withSubPats(typeTestTreeMaker :+ extractor.treeMaker(patBinderOrCasted, pos), extractor.subBindersAndPatterns: _*)
}
Expand Down
28 changes: 28 additions & 0 deletions test/files/pos/t6624.scala
@@ -0,0 +1,28 @@
sealed trait KList[+M[_]]

case class KCons[M[_], +T <: KList[M]](
tail: T
) extends KList[M]

case class KNil[M[_]]() extends KList[M]

object Test {
val klist: KCons[Option, KCons[Option, KCons[Option, KNil[Nothing]]]] = ???

// crashes with
// "Exception in thread "main" scala.reflect.internal.Types$TypeError: value _1 is not a member
// of KCons[Option,KCons[Option,KNil[Nothing]]]"
klist match {
case KCons(KCons(KCons(_))) =>
}

// fails with a similar message as an error, rather than a crash.
klist match {
case KCons(KCons(_)) =>
}

// succeeds
klist match {
case KCons(_) =>
}
}

0 comments on commit 32c5732

Please sign in to comment.