Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consider implicits constructor params in super-ctor call #3439

Closed
scabug opened this issue May 15, 2010 · 10 comments
Closed

consider implicits constructor params in super-ctor call #3439

scabug opened this issue May 15, 2010 · 10 comments
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented May 15, 2010

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)
@scabug
Copy link
Author

scabug commented May 15, 2010

Imported From: https://issues.scala-lang.org/browse/SI-3439?orig=1
Reporter: Oscar Forero (oforero)

@scabug
Copy link
Author

scabug commented May 15, 2010

@paulp said:
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)
}

@scabug
Copy link
Author

scabug commented May 15, 2010

@paulp said:
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.)

@scabug
Copy link
Author

scabug commented May 25, 2010

@odersky said:
I could not reproduce this. Compiles OK for me.

@scabug
Copy link
Author

scabug commented May 25, 2010

@paulp said:
% 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]$$
{code}

@scabug
Copy link
Author

scabug commented May 25, 2010

@paulp said:
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)

@scabug
Copy link
Author

scabug commented Jul 10, 2012

@retronym said (edited on Jul 10, 2012 10:06:56 PM UTC):
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.

@scabug
Copy link
Author

scabug commented Aug 13, 2013

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

{code}
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)
}
{code}

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:

{code}
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)
}
{code}
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.

@scabug
Copy link
Author

scabug commented Aug 13, 2013

@retronym said (edited on Aug 13, 2013 8:13:42 AM UTC):
We might be able to let this one through with:

-        if (sym.isTopLevel)
+        if (sym.isTopLevel && !sym.isParameter)
          fail(ImplicitAtToplevel)

@scabug
Copy link
Author

scabug commented Oct 10, 2014

@retronym said:
scala/scala#4043

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants