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

NullPointerException using abstract class value #9934

Closed
scabug opened this issue Sep 22, 2016 · 11 comments
Closed

NullPointerException using abstract class value #9934

scabug opened this issue Sep 22, 2016 · 11 comments

Comments

@scabug
Copy link

scabug commented Sep 22, 2016

I have a very weird bug in my code.

I am using Scala 2.11.7 and also tried with 2.11.8.

Problem
I get a NullPointerException when trying to access an abstract class value that contains a default value.

Example

sealed abstract class Language(private val realName: String = "", val extensions: List[String]) {
  self: Product =>

  val name = if(realName.nonEmpty) realName else self.productPrefix
}

case object Scala extends Language(extensions = List(".scala"))

I not always get a NullPointerException, it only happens in the tests if I run all the tests. If I run the test that fails with testOnly it passes.

I was going crazy since yesterday and today I had the idea to change the code to explicitly pass the "default":

sealed abstract class Language(private val realName: Option[String], val extensions: List[String]) {
  self: Product =>

  val name = realName.getOrElse(self.productPrefix)
}

case object Scala extends Language(realName = None, extensions = List(".scala"))

And now it works fine.

Do you have any ideas about what can be going wrong here?

EDIT:

The line 134 is the one with val specificTypeRules ....

object IgnoreManager {
  private[this] lazy val languageIgnoreConfigEnum: Map[String, List[SomeCaseClass]] = ...

  private[this] def languageSpecificRules(ignoreRules: List[ProjectIgnoreRules], language: Language.Language) = {
    val specificTypeRules = languageIgnoreConfigEnum.get(language.name)
    .....
  }
...
}
[info]   java.lang.NullPointerException:
[info]   at rules.project.filerules.IgnoreManager$.languageSpecificRules(IgnoreManager.scala:134)
[info]   at rules.project.filerules.IgnoreManager$.annotateWithIgnored(IgnoreManager.scala:264)
[info]   at rules.project.filerules.IgnoreManagerTests$$anonfun$1.apply$mcV$sp(IgnoreManagerTests.scala:29)
[info]   at rules.project.filerules.IgnoreManagerTests$$anonfun$1.apply(IgnoreManagerTests.scala:28)
[info]   at rules.project.filerules.IgnoreManagerTests$$anonfun$1.apply(IgnoreManagerTests.scala:28)
[info]   at org.scalatest.Transformer$$anonfun$apply$1.apply$mcV$sp(Transformer.scala:22)
[info]   at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
[info]   at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:22)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:20)
[info]   ...

I just updated the base classes and the rest of the code like it was, before I started changing it (as best as I could). I did lots of testing before understanding the error and I mostly did not commit before I had it fixed.

@scabug
Copy link
Author

scabug commented Sep 22, 2016

Imported From: https://issues.scala-lang.org/browse/SI-9934?orig=1
Reporter: Rodrigo Fernandes (rtfpessoa)
Affected Versions: 2.11.7, 2.11.8
See #5366

@scabug
Copy link
Author

scabug commented Sep 27, 2016

@SethTisue said:
are you able to reduce this to a self-contained, minimized piece of code that we can compile on our own computers?

@scabug
Copy link
Author

scabug commented Sep 27, 2016

Rodrigo Fernandes (rtfpessoa) said (edited on Sep 27, 2016 5:19:29 PM UTC):
@SethTisue that is something I could not do, but it seems very similar to #5366.

This only happened when running all the tests. If I ever did testOnly it would work just fine. Completely weird.

I know this is very few information. But all my tests would never replicate this in an isolated way.

Edit: I only found that #5366 was related after I created this issue. I could not get it by the title.

@scabug
Copy link
Author

scabug commented Sep 27, 2016

@som-snytt said:
I didn't see a cycle in the example, but a stack trace would narrow the field, so to speak. Narrow the field! That was totally by accident.

@scabug
Copy link
Author

scabug commented Sep 27, 2016

Rodrigo Fernandes (rtfpessoa) said:
The field that fails when accessed is the name. It uses the realName that apparently can be null at times.

@scabug
Copy link
Author

scabug commented Sep 27, 2016

@som-snytt said:
name isn't lazy, so it would have to throw at construction, not on access. The default realName is just None; if the module field is null, then $module.default might throw. Finally, the anon fun for the getOrElse could throw. It receives a ref to this, to invoke productPrefix, which is just a constant string. So I think the actual stack trace could, like, blow my mind.

@scabug
Copy link
Author

scabug commented Sep 28, 2016

Rodrigo Fernandes (rtfpessoa) said:
I am working to get a full description of the code and stacktrace. Will get back here when I can replicate it again.

@scabug
Copy link
Author

scabug commented Sep 28, 2016

Rodrigo Fernandes (rtfpessoa) said:
@som-snytt just updated the ticket. Take a look and see if it helps.

@scabug
Copy link
Author

scabug commented Sep 28, 2016

@som-snytt said (edited on Sep 28, 2016 7:49:19 PM UTC):
So the null value is either the private this lazy val or the object that's passed in. Probably the object reference isn't initialized, wherever it's coming from, as in the linked ticket.

@scabug
Copy link
Author

scabug commented Sep 28, 2016

Rodrigo Fernandes (rtfpessoa) said:
@som-snytt I can say with lots of certainty that is the name . Since it happens in other usages of it, and I looked at it while debugging.

@scabug
Copy link
Author

scabug commented Nov 7, 2016

@SethTisue said:
we can reopen if this gets narrowed down

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