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

consider implicits contributed by context bounds in super-ctor call

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Misc Compiler
    • Labels:

      Description

      The compiler fails compiling the following code:

      abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
      case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
      
      [error] could not find implicit value for evidence parameter of type Manifest[M]
      [error] case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
      [error]                                ^
      

      This same line compile without problem in the Scala console. It is possible to workaround this issue by adding the type parameter to the extended class:

      abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
      case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage[M](msg)
      

        Issue Links

          Activity

          Hide
          Paul Phillips added a comment -

          I told him to open this ticket, but maybe this is a known limitation. But I'm not sure where the difference in fidelity arises. Here is the equivalent of what the interpreter does, which does compile.

          object o1 {
            abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
          }
          object o2 {
            import o1._
            case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
          }
          
          Show
          Paul Phillips added a comment - I told him to open this ticket, but maybe this is a known limitation. But I'm not sure where the difference in fidelity arises. Here is the equivalent of what the interpreter does, which does compile. object o1 { abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg } } object o2 { import o1._ case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg) }
          Hide
          Paul Phillips added a comment -

          Oh interesting. Even this works.

          object o {
            abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
            case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg) { }
          }
          

          And trying to pass msg explicitly upward heads toward illustrating why. Is the reported version even supposed to compile? The message implies the equivalent implicit is disallowed, which would mean it's sneaking past in the context bound.

          // a.scala
          abstract class ParametricMessage[M](msg: M)(implicit m: Manifest[M]) { def message = msg }
          case class ParametricMessage1[M](msg: M, p1: Class[_])(implicit m: Manifest[M]) extends ParametricMessage(msg)(m) { }
          
          % scalac a.scala
          a.scala:3: error: `implicit' modifier cannot be used for top-level objects
            case class ParametricMessage1[M](msg: M, p1: Class[_])(implicit m: Manifest[M]) extends ParametricMessage(msg)(m) { }
          

          (BTW it's the same if it's not a case class - at first I thought it was something arising from the companion object, but no.)

          Show
          Paul Phillips added a comment - Oh interesting. Even this works. object o { abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg } case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg) { } } And trying to pass msg explicitly upward heads toward illustrating why. Is the reported version even supposed to compile? The message implies the equivalent implicit is disallowed, which would mean it's sneaking past in the context bound. // a.scala abstract class ParametricMessage[M](msg: M)(implicit m: Manifest[M]) { def message = msg } case class ParametricMessage1[M](msg: M, p1: Class[_])(implicit m: Manifest[M]) extends ParametricMessage(msg)(m) { } % scalac a.scala a.scala:3: error: `implicit' modifier cannot be used for top-level objects case class ParametricMessage1[M](msg: M, p1: Class[_])(implicit m: Manifest[M]) extends ParametricMessage(msg)(m) { } (BTW it's the same if it's not a case class - at first I thought it was something arising from the companion object, but no.)
          Hide
          Martin Odersky added a comment -

          I could not reproduce this. Compiles OK for me.

          Show
          Martin Odersky added a comment - I could not reproduce this. Compiles OK for me.
          Hide
          Paul Phillips added a comment -

          % scalac28 -version
          Scala compiler version 2.8.0.r22025-b20100524152851 – Copyright 2002-2010, LAMP/EPFL

          % scalac28 a.scala
          a.scala:2: error: could not find implicit value for evidence parameter of type Manifest[M]
          case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
          ^
          one error found

          % cat a.scala
          abstract class ParametricMessage[M: Manifest](msg: M)

          { def message = msg }

          case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)[paulp@jon 3439]$$

          Show
          Paul Phillips added a comment - % scalac28 -version Scala compiler version 2.8.0.r22025-b20100524152851 – Copyright 2002-2010, LAMP/EPFL % scalac28 a.scala a.scala:2: error: could not find implicit value for evidence parameter of type Manifest [M] case class ParametricMessage1 [M: Manifest] (msg: M, p1: Class [_] ) extends ParametricMessage(msg) ^ one error found % cat a.scala abstract class ParametricMessage [M: Manifest] (msg: M) { def message = msg } case class ParametricMessage1 [M: Manifest] (msg: M, p1: Class [_] ) extends ParametricMessage(msg) [paulp@jon 3439] $$
          Hide
          Paul Phillips added a comment -

          Grrr, I hosed my formatting. Here is the source again.

          abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
          case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
          
          Show
          Paul Phillips added a comment - Grrr, I hosed my formatting. Here is the source again. abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg } case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
          Hide
          Jason Zaugg added a comment - - edited

          The weird and wonderful scopes of primary constructors.

          Let's examine this example:

          class Base[M](i: Int)
          
          class Derived()(implicit i: Int) extends Base({println(i); 0})
          

          Within the type completer for `Derived`.

           classSig
             templateSig
               parentTypes  -  cscope = context.outer.makeNewScope          // package <empty>
                typePrimaryConstrBody  -  namer.enterValueParams(vparamss)  // `implicit val i` will have the owner `package <empty>`
          
                 ...
                   typedArg  - fun = new [M]<empty>.this.Base[M][M].<init>
                               args = List({println(i);0})
                               i.sym.owner = package <empty>
          
                     ...
                        i.info
                          Namers#complete
                            ...
                               Namers#validate
                                  i.owner.isPackageClass = true // KABOOM
          
          

          Enclosing Derived in an object masks the problem.

          Adding an explicit type argument to the Base constructor invocation masks the problem.

          Note to future self: pinned down with -Yshow-syms -Ydebug -Ylog:namer; and subsequently caught the package-owned symbol i in Namers#logAssignSymbol.

          Show
          Jason Zaugg added a comment - - edited The weird and wonderful scopes of primary constructors. Let's examine this example: class Base[M](i: Int) class Derived()(implicit i: Int) extends Base({println(i); 0}) Within the type completer for `Derived`. classSig templateSig parentTypes - cscope = context.outer.makeNewScope // package <empty> typePrimaryConstrBody - namer.enterValueParams(vparamss) // `implicit val i` will have the owner `package <empty>` ... typedArg - fun = new [M]<empty>.this.Base[M][M].<init> args = List({println(i);0}) i.sym.owner = package <empty> ... i.info Namers#complete ... Namers#validate i.owner.isPackageClass = true // KABOOM Enclosing Derived in an object masks the problem. Adding an explicit type argument to the Base constructor invocation masks the problem. Note to future self: pinned down with -Yshow-syms -Ydebug -Ylog:namer ; and subsequently caught the package-owned symbol i in Namers#logAssignSymbol .
          Hide
          Jason Zaugg added a comment -

          Relatedly, in early initializers (https://groups.google.com/d/msg/scala-user/mR8nOx3ve-0/gSMnXWyY3l8J)

          class Summation[T : Summable](baseValue : Signal[T]) extends {
            private val _baseSignal = new Mutable[T, T](Val(implicitly[Summable[T]].zero), implicitly[Summable[T]].sum(_, _))
          } with WrappedSignal[T](_baseSignal) {
            def +=(value : Signal[T]) = _baseSignal.applyMutator(value)
          }
          

          I get an error on line two that it "could not find the implicit value for argument e/not enough arguments for method implicitly".

          On the second way:

          class Summation[T](baseValue : Signal[T]) (implicit summable : Summable[T]) extends {
            private val _baseSignal = new Mutable[T, T](Val(summable.zero), summable.sum(_, _))
          } with WrappedSignal[T](_baseSignal) {
            def +=(value : Signal[T]) = _baseSignal.applyMutator(value)
          }
          

          I get the compile error "implicit modifier cannot be used for top-level objects" on the first line. If I remove the reference to summable in the early initializer, then the compile error goes away, although this makes it impossible to pass the signal into the base class constructor.

          Show
          Jason Zaugg added a comment - Relatedly, in early initializers ( https://groups.google.com/d/msg/scala-user/mR8nOx3ve-0/gSMnXWyY3l8J ) class Summation[T : Summable](baseValue : Signal[T]) extends { private val _baseSignal = new Mutable[T, T](Val(implicitly[Summable[T]].zero), implicitly[Summable[T]].sum(_, _)) } with WrappedSignal[T](_baseSignal) { def +=(value : Signal[T]) = _baseSignal.applyMutator(value) } I get an error on line two that it "could not find the implicit value for argument e/not enough arguments for method implicitly". On the second way: class Summation[T](baseValue : Signal[T]) (implicit summable : Summable[T]) extends { private val _baseSignal = new Mutable[T, T](Val(summable.zero), summable.sum(_, _)) } with WrappedSignal[T](_baseSignal) { def +=(value : Signal[T]) = _baseSignal.applyMutator(value) } I get the compile error "implicit modifier cannot be used for top-level objects" on the first line. If I remove the reference to summable in the early initializer, then the compile error goes away, although this makes it impossible to pass the signal into the base class constructor.
          Hide
          Jason Zaugg added a comment - - edited

          We might be able to let this one through with:

          -        if (sym.isTopLevel)
          +        if (sym.isTopLevel && !sym.isParameter)
                    fail(ImplicitAtToplevel)
          
          Show
          Jason Zaugg added a comment - - edited We might be able to let this one through with: - if (sym.isTopLevel) + if (sym.isTopLevel && !sym.isParameter) fail(ImplicitAtToplevel)

            People

            • Assignee:
              Adriaan Moors
              Reporter:
              Oscar Forero
              TracCC:
              Paul Phillips
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:

                Development