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

Using this as default argument to constructor does not refer to enclosing object #5543

Closed
scabug opened this Issue Mar 4, 2012 · 14 comments

Comments

Projects
None yet
2 participants
@scabug
Copy link

scabug commented Mar 4, 2012

In the following code, the default argument to Bar is object Bar instead of object Main.

However, scalac requires that both Main and Bar conform to the parameter type.

I'd expect Main.this to be in scope, even though the expression is evaluated by Bar$.

Reproduce Code

package trythis

//object Main { // type mismatch
object Main extends Function0[Int] {

  class Bar(x: Function0[Int] = this) {
    override def toString = "X "+ x.toString +"="+ x()
  }
  object Bar extends Function0[Int] {
    def apply() = 21
    override def toString = "My Bar module"
  }
  def main(args: Array[String]): Unit = {
    println(new Bar())
  }
  override def toString = "My Main"
  def apply() = 17
}

Expected result

X My Main=17

Actual Result

X My Bar module=21
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 4, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5543?orig=1
Reporter: @som-snytt
Affected Versions: 2.10.0-M2, 2.10.0
Other Milestones: 2.10.0

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 6, 2012

@cvogt said:
please re-assign, if you are not the right person

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 23, 2012

@som-snytt said:
I took a look and submitted a pull request.

scala/scala#317

The problem seems to be that when default-getters for constructors are added to the companion module, the expression has the module in scope.

Adding constrTyperIf(flag) before entering typedDefDef seems to work.

Since there is no flag for default-getter for ctor, it does a name compare. It might be preferable to add a flag or abuse an existing flag instead.

This change includes renaming init$default$ to init$$default$ to avoid collisions with default-getters for an ordinary method on the module named init.

That change is not trivial, so guidance is needed. Alternatively, one could live with the possibility of name collision and just allow that there are interactions that impose limits, similar to #5366.

More example:

object A {
  val v = 7
  class B(val x: Int = v)
  object B {
    val v = 5
    //def init(y: Int = v) = y  // names collide
  }
  def main(args: Array[String]) {
    println(new B().x) // 5
  }
}
@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 5, 2012

@som-snytt said:
77b577a5aeab782b64b39b3a812c35fdd8ab265a
in
scala/scala#317

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jan 28, 2013

@lrytz said:
The fix goes too far because it also affects this references of auxiliary constructors.

object T {
  override def toString = "T"

  // here, `this` should refer to T. That's what was fixed
  class C(val x: Any = this) {
    override def toString() = "C"
  }

  class D(val x: Any) {
    override def toString() = "D"
    // here, `this` should refer to the D instance, but after the fix it also
    // refers to T.
    def this(a: Int, b: Int, c: Any = this) { this(c) }
  }
}

println((new T.C()).x)     // prints "T", correct
println((new T.D(0,0)).x)  // prints "T", should print "D"
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jan 28, 2013

@lrytz said:
actually i changed my mind, the fix / current behavior is correct. it doesn't make sense to have the class members in scope when typing (auxiliary or primary) constructor defaults (or types).

class C { type T; def this(x: T) { this() } }                 // gives `not found: type T`
class C(x: Int) { def this(a: Int, b: Int = x) { this(b) } }  // gives `not found: value x`
class C { val x = 0; def this(a: Int = x) { this() } }        // also  `not found: value x`

spec 5.3.1: The signature and the self constructor invocation of a constructor definition are type-checked and evaluated in the scope which is in effect at the point of the enclosing class definition, augmented by any type parameters of the enclosing class and by any early definitions of the enclosing template. The rest of the constructor expression is type-checked and evaluated as a function body in the current class.

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jan 28, 2013

@retronym said:
If you haven't already, could you please add a test that demonstrates that behaviour?

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jan 29, 2013

@lrytz said:
sure, will be part of the upcoming namer pull request

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 19, 2015

@adriaanm said:
Featured in Scala puzzlers just now :-) Should we really allow referring to this in defaults? This should not compile, but does:

object Foo {
case class Foo(x: String = this.toString)
}

Let's reboot the discussion.

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 19, 2015

@adriaanm said:
I want to focus on the next puzzler, so didn't look to closely at the rest of the ticket.

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 19, 2015

@som-snytt said:
Since this was my first ever contribution, and since I have to pick up my daughter to see the Met rebroadcast of La donna del lago so my day isn't a total bust, I'll go with my initial assessment. Not that I knew anything back then,

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 19, 2015

@som-snytt said:
P.S. Damn you, Scala Puzzlers! Damn you to perdition's flame!

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Mar 19, 2015

@som-snytt said:
The comment on the puzzler was that this is another issue.

In the U.S., you get three years to amend a tax return and three years to amend a community contribution.

But if you're lucky, it won't get fixed before the second edition of the puzzlers book.

However, that should have read:

You're lucky if Jason doesn't notice the issue, assign it to himself and fix it before Scala Days. 
Or rather, at Scala Days during lunch the day of your presentation. Or maybe during the five
minutes you give people to figure out what's going on.
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jun 6, 2015

@som-snytt said:
Reclosing because the Puzzlers at ScalaDays should not result in an orgy of second-guessing. "Feel free to open a new ticket." What is the prize for being lucky 10000? Are we confident that Jira doesn't overflow?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.