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

Value class with method signature dependent on constructor parameter = crash

    Details

      Description

      trait Path {
        type Dep
      }
      
      final class ValueClass[P <: Path](val path: P) extends AnyVal {
        import path._
        def apply(dep: Dep): Dep = dep
      }
      

      Gives:

      uncaught exception during compilation: scala.reflect.internal.Types$TypeError
      scala.reflect.internal.Types$TypeError: type mismatch;
       found   : ValueClass[P]#path.Dep
       required: ValueClass.this.path.Dep
      	at scala.tools.nsc.typechecker.Contexts$Context.issueCommon(Contexts.scala:375)
      	at scala.tools.nsc.typechecker.Contexts$Context.issue(Contexts.scala:379)
      	at scala.tools.nsc.typechecker.ContextErrors$ErrorUtils$.issueTypeError(ContextErrors.scala:84)
      	at scala.tools.nsc.typechecker.ContextErrors$ErrorUtils$.issueNormalTypeError(ContextErrors.scala:69)
      	at scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen$.AdaptTypeError(ContextErrors.scala:176)
      	at scala.tools.nsc.typechecker.Typers$Typer.fallBack$1(Typers.scala:1249)
      	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1254)
      	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5467)
      	at scala.tools.nsc.interpreter.ReplGlobal$$anon$1$$anon$2.typed(ReplGlobal.scala:29)
      	at scala.tools.nsc.typechecker.Typers$Typer.transformedOrTyped(Typers.scala:5658)
      	at scala.tools.nsc.typechecker.Typers$Typer.typedDefDef(Typers.scala:2169)
      	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5386)
      	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5458)
      	at scala.tools.nsc.interpreter.ReplGlobal$$anon$1$$anon$2.typed(ReplGlobal.scala:29)
      	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5509)
      	at scala.tools.nsc.typechecker.Typers$Typer.typedPos(Typers.scala:5514)
      	at scala.tools.nsc.transform.ExtensionMethods$Extender$$anonfun$transformStats$1$$anonfun$11$$anonfun$apply$7.apply(ExtensionMethods.scala:191)
      	at scala.tools.nsc.transform.ExtensionMethods$Extender$$anonfun$transformStats$1$$anonfun$11$$anonfun$apply$7.apply(ExtensionMethods.scala:191)
      	at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2872)
      	at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:34)
      	at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:28)
      	at scala.tools.nsc.transform.ExtensionMethods$Extender$$anonfun$transformStats$1$$anonfun$11.apply(ExtensionMethods.scala:191)
      	at scala.tools.nsc.transform.ExtensionMethods$Extender$$anonfun$transformStats$1$$anonfun$11.apply(ExtensionMethods.scala:190)
      

      By contrast, this compiles:

      final class ValueClass[P <: Path](val path: P) extends AnyVal {
        import path._
        def apply(dep: Dep): Dep = dep
      }
      

      Although even in the second case, the signature appears incorrect:

      final def apply$extension[P >: Nothing <: Path]($this: ValueClass[P])(dep: ValueClass.this.path.Dep): Path#Dep = dep;
      

      The formal type of the parameter `dep` should have a substitution applied from ValueClass.this.type -> $this.type.

        Issue Links

          Activity

          Hide
          Eugene Burmako added a comment -

          Looks like the working example is missing a line or two.

          Show
          Eugene Burmako added a comment - Looks like the working example is missing a line or two.
          Hide
          Jason Zaugg added a comment - - edited

          This must be close to a fix, but it still crashes:

          diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
          index 6cc957a..e5d30eb 100644
          --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
          +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
          @@ -124,7 +124,8 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
                     MethodType(List(thisParam), restpe)
                 }
                 val GenPolyType(tparams, restpe) = origInfo cloneInfo extensionMeth
          -      GenPolyType(tparams ::: newTypeParams, transform(restpe) substSym (clazz.typeParams, newTypeParams))
          +      val newResType = transform(restpe) substThisAndSym (clazz, singleType(currentOwner.companionModule.thisType, thisParam), clazz.typeParams, ne
          +      GenPolyType(tparams ::: newTypeParams, newResType)
               }
           
               private def allParams(tpe: Type): List[Symbol] = tpe match {
          
            last tree to typer: Ident(dep)
                        symbol: value dep (flags: <param> <triedcooking>)
             symbol definition: dep: $this.path.Dep
                 symbol owners: value dep -> method apply$extension -> object ValueClass -> package <empty>
                context owners: method apply$extension -> object ValueClass -> package <empty>
          
          // final def apply$extension[P <: Path]($this: ValueClass[P])(dep: $this.path.Dep): $this.path.Dep in object ValueClass
          
          uncaught exception during compilation: scala.reflect.internal.Types$TypeError
          error: scala.reflect.internal.Types$TypeError: type mismatch;
           found   : ValueClass[P]#path.Dep
           required: $this.path.Dep
          

          One for another day...

          Show
          Jason Zaugg added a comment - - edited This must be close to a fix, but it still crashes: diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 6cc957a..e5d30eb 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -124,7 +124,8 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { MethodType(List(thisParam), restpe) } val GenPolyType(tparams, restpe) = origInfo cloneInfo extensionMeth - GenPolyType(tparams ::: newTypeParams, transform(restpe) substSym (clazz.typeParams, newTypeParams)) + val newResType = transform(restpe) substThisAndSym (clazz, singleType(currentOwner.companionModule.thisType, thisParam), clazz.typeParams, ne + GenPolyType(tparams ::: newTypeParams, newResType) } private def allParams(tpe: Type): List[Symbol] = tpe match { last tree to typer: Ident(dep) symbol: value dep (flags: <param> <triedcooking>) symbol definition: dep: $this.path.Dep symbol owners: value dep -> method apply$extension -> object ValueClass -> package <empty> context owners: method apply$extension -> object ValueClass -> package <empty> // final def apply$extension[P <: Path]($this: ValueClass[P])(dep: $this.path.Dep): $this.path.Dep in object ValueClass uncaught exception during compilation: scala.reflect.internal.Types$TypeError error: scala.reflect.internal.Types$TypeError: type mismatch; found : ValueClass[P]#path.Dep required: $this.path.Dep One for another day...
          Hide
          Jason Zaugg added a comment -

          Another example:

          class YouAreYourself[A <: AnyRef](val you: A) extends AnyVal {
            def yourself: you.type = you
          }
          
          Show
          Jason Zaugg added a comment - Another example: class YouAreYourself[A <: AnyRef](val you: A) extends AnyVal { def yourself: you.type = you }
          Show
          Jason Zaugg added a comment - https://github.com/scala/scala/pull/1912

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              Jason Zaugg
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development