From a2cba53e18864a5b9092f1e329c6e0afb09566c5 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 25 Jul 2016 10:21:26 +1000 Subject: SD-167 Fine tuning constructor pattern translation - Avoid calling NoSymbol.owner when checking whether we're dealing with a case class constructor pattern or a general extractor. Tested manually with the test case in the ticket, no more output is produced under `-Xdev`. - Be more conservative about the conversion to a case class pattern: rather than looking just at the type of the pattern tree, also look at the tree itself to ensure its safe to elide. This change is analagous to SI-4859, which restricted rewrites of case apply calls to case constructors. I've manually tested that case class patterns are still efficiently translated: ``` object Test { def main(args: Array[String]) { Some(1) match { case Some(x) => } } } ``` ``` % qscalac -Xprint:patmat sandbox/test.scala [[syntax trees at end of patmat]] // test.scala package { object Test extends scala.AnyRef { def (): Test.type = { Test.super.(); () }; def main(args: Array[String]): Unit = { case val x1: Some[Int] = scala.Some.apply[Int](1); case4(){ if (x1.ne(null)) matchEnd3(()) else case5() }; case5(){ matchEnd3(throw new MatchError(x1)) }; matchEnd3(x: Unit){ x } } } } ``` --- src/compiler/scala/tools/nsc/typechecker/Namers.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index ad9377f8b4..caad4a907b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1764,7 +1764,7 @@ trait Namers extends MethodSynthesis { * bugs waiting to be reported? If not, why not? When exactly do we need to * call this method? */ - def companionSymbolOf(original: Symbol, ctx: Context): Symbol = { + def companionSymbolOf(original: Symbol, ctx: Context): Symbol = if (original == NoSymbol) NoSymbol else { val owner = original.owner // SI-7264 Force the info of owners from previous compilation runs. // Doing this generally would trigger cycles; that's what we also diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala index f90e61ff92..1df3449ce6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala @@ -79,6 +79,7 @@ trait PatternTypers { // 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) val fun = inPlaceAdHocOverloadingResolution(fun0)(hasUnapplyMember) + val canElide = treeInfo.isQualifierSafeToElide(fun) val caseClass = companionSymbolOf(fun.tpe.typeSymbol.sourceModule, context) val member = unapplyMember(fun.tpe) def resultType = (fun.tpe memberType member).finalResultType @@ -94,7 +95,7 @@ trait PatternTypers { // Dueling test cases: pos/overloaded-unapply.scala, run/case-class-23.scala, pos/t5022.scala // A case class with 23+ params has no unapply method. // A case class constructor may be overloaded with unapply methods in the companion. - if (caseClass.isCase && !member.isOverloaded) + if (canElide && caseClass.isCase && !member.isOverloaded) logResult(s"convertToCaseConstructor($fun, $caseClass, pt=$pt)")(convertToCaseConstructor(fun, caseClass, pt)) else if (!reallyExists(member)) CaseClassConstructorError(fun, s"${fun.symbol} is not a case class, nor does it have an unapply/unapplySeq member") -- cgit v1.2.3