Scala Programming Language
  1. Scala Programming Language
  2. SI-3353

default argument desugaring does not properly deal with patterns

    Details

      Description

      [extempore says: this is an intersection of implicit + default + unapply. If we let it get past the NPE (which is from a Block not having a symbol) we see what has happened:

      "foo" match {
        case {
          val x$$1: java.lang.String = <unapply-selector>;
          val x$$2: Option[String] = TestingObject.this.Matcher.unapply$$default$$2(x$$1);
          TestingObject.this.Matcher.unapply(x$$1)(x$$2)
        } <unapply> ((x @ _)) => scala.this.Predef.println(x)
      };
      

      There is nothing in place to deal with symbol-free Blocks popping up inside patterns.

      – original report follows –

      Here's the class being compiled.
      It compiles fine if an implicit val is defined in main().

      object TestingObject {
      
          "foo" match {
            case Matcher(result) => println(result)
          }
      
        object Matcher{
          def unapply(s: String)(implicit secondParam: Option[String] = None) = Some("Got: " + s + " and " + secondParam)
        }
      }
      

      Here's the error the compiler throws:

      Exception in thread "main" java.lang.NullPointerException
      	at scala.tools.nsc.typechecker.Unapplies$$class.unapplyTypeList(Unapplies.scala:30)
      	at scala.tools.nsc.Global$$analyzer$$.unapplyTypeList(Global.scala:291)
      	at scala.tools.nsc.typechecker.Typers$$Typer.doTypedApply(Typers.scala:2509)
      	at scala.tools.nsc.typechecker.Typers$$Typer.doTypedApply(Typers.scala:2424)
      	at scala.tools.nsc.typechecker.Typers$$Typer.typedApply$$1(Typers.scala:3285)
      	at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3919)
      	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4073)
      	at scala.tools.nsc.typechecker.Typers$$Typer.typedPattern(Typers.scala:4161)
      	at scala.tools.nsc.typechecker.Typers$$Typer.typedCase(Typers.scala:1904)
      	at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$typedCases$$1.apply(Typers.scala:1927)
      	...
      

        Activity

        Hide
        Gilles Dubochet added a comment -

        Removed IDEA-specific bits of the stack trace. Assigned to Martin as this is a typer error.

        Show
        Gilles Dubochet added a comment - Removed IDEA-specific bits of the stack trace. Assigned to Martin as this is a typer error.
        Hide
        Paul Phillips added a comment -

        Reassigning to rytz with new description to get it back in the hopper.

        Show
        Paul Phillips added a comment - Reassigning to rytz with new description to get it back in the hopper.
        Hide
        Lukas Rytz added a comment -

        OK, I see.. I'm not sure what to do.

        Using default arguments in patterns is currently not supported, the fact that it's not disallowed for this extractor is rather a missed case, maybe we should disallow it for now.

        There's a whole space to explore on the interaction of named/default arguments and pattern matching. If we start doing this, we will end up with this kind of blocks during pattern matching (and btw, blocks don't need to have symbols).

        Show
        Lukas Rytz added a comment - OK, I see.. I'm not sure what to do. Using default arguments in patterns is currently not supported, the fact that it's not disallowed for this extractor is rather a missed case, maybe we should disallow it for now. There's a whole space to explore on the interaction of named/default arguments and pattern matching. If we start doing this, we will end up with this kind of blocks during pattern matching (and btw, blocks don't need to have symbols).
        Hide
        Hubert Plociniczak added a comment -

        Just as a side note. Bug #4425 was closed because it no longer crashes, but the thing is it currently gives a wrong error message and is related to whatever is decided for this bug. So once we fix this bug, test for #4425 needs to be fixed as well.

        Show
        Hubert Plociniczak added a comment - Just as a side note. Bug #4425 was closed because it no longer crashes, but the thing is it currently gives a wrong error message and is related to whatever is decided for this bug. So once we fix this bug, test for #4425 needs to be fixed as well.
        Hide
        Miguel Garcia added a comment -

        Still crashing:

        Welcome to Scala version 2.10.0-20120502-222338-24be606216 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
        Type in expressions to have them evaluated.
        Type :help for more information.
        
        scala> object TestingObject {
             |
             |     "foo" match {
             |       case Matcher(result) => println(result)
             |     }
             |
             |   object Matcher{
             |     def unapply(s: String)(implicit secondParam: Option[String] = None) = Some("Got: " + s + " and " + secondParam)
             |   }
             | }
        error:
             while compiling:  <console>
               current phase:  typer
             library version:  version 2.10.0-20120502-222338-24be606216
            compiler version:  version 2.10.0-20120502-222338-24be606216
          reconstructed args:
        
        uncaught exception during compilation: java.lang.NullPointerException
        java.lang.NullPointerException
                at scala.tools.nsc.typechecker.Unapplies$class.unapplyTypeList(Unapplies.scala:28)
                at scala.tools.nsc.interpreter.ReplGlobal$$anon$1.unapplyTypeList(ReplGlobal.scala:24)
                at scala.tools.nsc.typechecker.Typers$Typer.doTypedApply(Typers.scala:3046)
                at scala.tools.nsc.typechecker.Typers$Typer.doTypedApply(Typers.scala:2994)
                at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:4111)
                at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4819)
                at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4992)
                at scala.tools.nsc.interpreter.ReplGlobal$$anon$1$$anon$2.typed(ReplGlobal.scala:29)
                at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedPattern$1.apply(Typers.scala:5106)
                at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedPattern$1.apply(Typers.scala:5106)
                at scala.tools.nsc.typechecker.Contexts$Context.withImplicitsDisabledAllowEnrichment(Contexts.scala:211)
                at scala.tools.nsc.typechecker.Typers$Typer.typedPattern(Typers.scala:5106)
                at scala.tools.nsc.typechecker.Typers$Typer.typedCase(Typers.scala:2156)
                at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedCases$1.apply(Typers.scala:2206)
                at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedCases$1.apply(Typers.scala:2205)
                at scala.collection.immutable.List.loop$1(List.scala:163)
                at scala.collection.immutable.List.mapConserve(List.scala:179)
                at scala.tools.nsc.typechecker.Typers$Typer.typedCases(Typers.scala:2205)
                at scala.tools.nsc.typechecker.Typers$Typer.typedMatch(Typers.scala:2220)
        
        Show
        Miguel Garcia added a comment - Still crashing: Welcome to Scala version 2.10.0-20120502-222338-24be606216 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29). Type in expressions to have them evaluated. Type :help for more information. scala> object TestingObject { | | "foo" match { | case Matcher(result) => println(result) | } | | object Matcher{ | def unapply(s: String)(implicit secondParam: Option[String] = None) = Some("Got: " + s + " and " + secondParam) | } | } error: while compiling: <console> current phase: typer library version: version 2.10.0-20120502-222338-24be606216 compiler version: version 2.10.0-20120502-222338-24be606216 reconstructed args: uncaught exception during compilation: java.lang.NullPointerException java.lang.NullPointerException at scala.tools.nsc.typechecker.Unapplies$class.unapplyTypeList(Unapplies.scala:28) at scala.tools.nsc.interpreter.ReplGlobal$$anon$1.unapplyTypeList(ReplGlobal.scala:24) at scala.tools.nsc.typechecker.Typers$Typer.doTypedApply(Typers.scala:3046) at scala.tools.nsc.typechecker.Typers$Typer.doTypedApply(Typers.scala:2994) at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:4111) at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4819) at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4992) at scala.tools.nsc.interpreter.ReplGlobal$$anon$1$$anon$2.typed(ReplGlobal.scala:29) at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedPattern$1.apply(Typers.scala:5106) at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedPattern$1.apply(Typers.scala:5106) at scala.tools.nsc.typechecker.Contexts$Context.withImplicitsDisabledAllowEnrichment(Contexts.scala:211) at scala.tools.nsc.typechecker.Typers$Typer.typedPattern(Typers.scala:5106) at scala.tools.nsc.typechecker.Typers$Typer.typedCase(Typers.scala:2156) at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedCases$1.apply(Typers.scala:2206) at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedCases$1.apply(Typers.scala:2205) at scala.collection.immutable.List.loop$1(List.scala:163) at scala.collection.immutable.List.mapConserve(List.scala:179) at scala.tools.nsc.typechecker.Typers$Typer.typedCases(Typers.scala:2205) at scala.tools.nsc.typechecker.Typers$Typer.typedMatch(Typers.scala:2220)
        Hide
        Adriaan Moors added a comment -

        I can fix this in the new pattern matcher, but first names-defaults has to support leaving the dummy <unapply-selector> in place for an unapply call with defaults
        A reference to `argDummy` (see below) should not be extracted to a new local variable.

        val argDummy  = context.owner.newValue(nme.SELECTOR_DUMMY, fun.pos, SYNTHETIC) setInfo pt
        
        Show
        Adriaan Moors added a comment - I can fix this in the new pattern matcher, but first names-defaults has to support leaving the dummy <unapply-selector> in place for an unapply call with defaults A reference to `argDummy` (see below) should not be extracted to a new local variable. val argDummy = context.owner.newValue(nme.SELECTOR_DUMMY, fun.pos, SYNTHETIC) setInfo pt
        Hide
        Adriaan Moors added a comment - - edited
        {
                val x$1: String = <unapply-selector>;
                val x$2: Option[String] = TestingObject.this.Matcher.unapply$default$2(x$1);
                TestingObject.this.Matcher.unapply(x$1)(x$2)
        }
        

        should be

        {
                val x$1: Option[String] = TestingObject.this.Matcher.unapply$default$1();
                TestingObject.this.Matcher.unapply(<unapply-selector>)(x$1)
        }
        
        Show
        Adriaan Moors added a comment - - edited { val x$1: String = <unapply-selector>; val x$2: Option[String] = TestingObject.this.Matcher.unapply$default$2(x$1); TestingObject.this.Matcher.unapply(x$1)(x$2) } should be { val x$1: Option[String] = TestingObject.this.Matcher.unapply$default$1(); TestingObject.this.Matcher.unapply(<unapply-selector>)(x$1) }
        Hide
        Adriaan Moors added a comment -

        in the mean time, an implementation restriction would be a good enough fix for 2.10.1-RC1

        Show
        Adriaan Moors added a comment - in the mean time, an implementation restriction would be a good enough fix for 2.10.1-RC1
        Show
        Lukas Rytz added a comment - https://github.com/scala/scala/pull/2043

          People

          • Assignee:
            Lukas Rytz
            Reporter:
            Graham Lea
            TracCC:
            Erik Engbrecht, Graham Lea, Paul Phillips
          • Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development