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

NPE in when completing default getters #6576

Closed
scabug opened this issue Oct 28, 2012 · 21 comments
Closed

NPE in when completing default getters #6576

scabug opened this issue Oct 28, 2012 · 21 comments

Comments

@scabug
Copy link

@scabug scabug commented Oct 28, 2012

I get the following exception in the IDE when opening certain files. I couldn't nail it down to a specific file yet, but git archeology suggests an existing workaround was removed with the belief that the NPE can't happen anymore:

module.attachments.get[ConstructorDefaultsAttachment] match {
  // by martin: the null case can happen in IDE; this is really an ugly hack on top of an ugly hack but it seems to work
  // later by lukas: disabled when fixing SI-5975, i think it cannot happen anymore
  case Some(cda) /*if cma.companionModuleClassNamer == null*/ =>
    val p = (cda.classWithDefault, cda.companionModuleClassNamer)
    moduleNamer = Some(p)
    p
java.lang.NullPointerException
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$addDefaultGetters$2$$anonfun$apply$14.apply(Namers.scala:1169)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$addDefaultGetters$2.apply(Namers.scala:1102)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$addDefaultGetters$2.apply(Namers.scala:1099)
	at scala.collection.LinearSeqOptimized$class.foldLeft(LinearSeqOptimized.scala:110)
	at scala.collection.immutable.List.foldLeft(List.scala:78)
	at scala.tools.nsc.typechecker.Namers$Namer.addDefaultGetters(Namers.scala:1099)
	at scala.tools.nsc.typechecker.Namers$Namer.methodSig(Namers.scala:1027)
	at scala.tools.nsc.typechecker.Namers$Namer.getSig$1(Namers.scala:1305)
	at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1347)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply$mcV$sp(Namers.scala:709)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:708)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:708)
	at scala.tools.nsc.typechecker.Namers$Namer.scala$tools$nsc$typechecker$Namers$Namer$$logAndValidate(Namers.scala:1385)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:708)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:707)
	at scala.tools.nsc.typechecker.Namers$$anon$1.completeImpl(Namers.scala:1496)
	at scala.tools.nsc.typechecker.Namers$LockingTypeCompleter$class.complete(Namers.scala:1504)
	at scala.tools.nsc.typechecker.Namers$$anon$1.complete(Namers.scala:1494)
	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1217)
	at scala.reflect.internal.Symbols$Symbol.paramss(Symbols.scala:1473)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$DefOwner$class.addDef(ScalaStructureBuilder.scala:668)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$Builder.addDef(ScalaStructureBuilder.scala:871)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$DefOwner$class.addDef(ScalaStructureBuilder.scala:658)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$Builder.addDef(ScalaStructureBuilder.scala:871)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser.traverse(ScalaStructureBuilder.scala:943)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser$$anonfun$traverse$1.apply(ScalaStructureBuilder.scala:950)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser$$anonfun$traverse$1.apply(ScalaStructureBuilder.scala:950)
	at scala.collection.immutable.List.foreach(List.scala:309)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser.traverse(ScalaStructureBuilder.scala:950)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser$$anonfun$traverse$1.apply(ScalaStructureBuilder.scala:950)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser$$anonfun$traverse$1.apply(ScalaStructureBuilder.scala:950)
	at scala.collection.immutable.List.foreach(List.scala:309)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser.traverse(ScalaStructureBuilder.scala:950)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser$$anonfun$traverse$1.apply(ScalaStructureBuilder.scala:950)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser$$anonfun$traverse$1.apply(ScalaStructureBuilder.scala:950)
	at scala.collection.immutable.List.foreach(List.scala:309)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser$TreeTraverser.traverse(ScalaStructureBuilder.scala:950)
	at scala.tools.eclipse.javaelements.ScalaStructureBuilder$StructureBuilderTraverser.traverse(ScalaStructureBuilder.scala:903)
	at scala.tools.eclipse.javaelements.ScalaCompilationUnit$$anonfun$buildStructure$2$$anonfun$apply$5$$anonfun$apply$1.apply$mcV$sp(ScalaCompilationUnit.scala:74)
	at scala.tools.eclipse.javaelements.ScalaCompilationUnit$$anonfun$buildStructure$2$$anonfun$apply$5$$anonfun$apply$1.apply(ScalaCompilationUnit.scala:73)
	at scala.tools.eclipse.javaelements.ScalaCompilationUnit$$anonfun$buildStructure$2$$anonfun$apply$5$$anonfun$apply$1.apply(ScalaCompilationUnit.scala:73)
	at scala.tools.nsc.util.InterruptReq.execute(InterruptReq.scala:26)
	at scala.tools.nsc.interactive.Global.pollForWork(Global.scala:331)
	at scala.tools.nsc.interactive.PresentationCompilerThread.run(PresentationCompilerThread.scala:22)
@scabug
Copy link
Author

@scabug scabug commented Oct 28, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6576?orig=1
Reporter: @dragos
Affected Versions: 2.10.1-RC1

@scabug
Copy link
Author

@scabug scabug commented Oct 28, 2012

@dragos said (edited on Oct 28, 2012 2:49:02 PM UTC):
I noticed that this error seems to be related to annotations. For instance, code in ProductN.scala (where I see this exception thrown quite often) has the following declaration:

  @throws(classOf[IndexOutOfBoundsException])
  override def productElement(n: Int) = n match { 
..

and throws takes a default argument:

class throws[T <: Throwable](cause: String = "") extends scala.annotation.StaticAnnotation {

@scabug
Copy link
Author

@scabug scabug commented Oct 28, 2012

@lrytz said:
this could be helpful; on the other hand, it might also just be due to the fact that we don't have many constructors with default arguments in our codebase; (case classes that are created through companion-apply would not count here, since they're not constructor calls).

@scabug
Copy link
Author

@scabug scabug commented Oct 29, 2012

@dragos said:
What could be helpful? :)

@scabug
Copy link
Author

@scabug scabug commented Oct 29, 2012

@lrytz said:
knowing that it happens when there are annotations..

@scabug
Copy link
Author

@scabug scabug commented Oct 29, 2012

@dragos said:
Ah, right. Yes, the compiler reports in the log the position in the tree where the exception occurred, and it is exactly the throws annotation. So it's not just a hunch, it's fact :) I still don't know what's the sequence of actions that gets it there..

@scabug
Copy link
Author

@scabug scabug commented Dec 4, 2012

@dragos said:
I'm seeing this quite often. Could we roll this into the compiler, either 2.10.x or next RC? It's simply reverting a commit that commented out a null check.

@scabug
Copy link
Author

@scabug scabug commented Dec 22, 2012

@paulp said:
I think this will be fixed (somewhat indirectly) by scala/scala#1801 . It was possible for erroneous annotations to cause typed to return a tree with a null type and without marking the tree erroneous, invariably leading to failure at some later and most likely surprising point.

@scabug
Copy link
Author

@scabug scabug commented Jan 7, 2013

@dragos said:
I'll assume this is fixed, and reopen if it happens again.

@scabug
Copy link
Author

@scabug scabug commented Feb 13, 2013

@adriaanm said:
still happens on 2.10.1-RC1:

(when switching branches, apparently)

eclipse.buildId=I20110613-1736
java.version=1.6.0_37
java.vendor=Apple Inc.
BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US
Framework arguments:  -product org.eclipse.epp.package.java.product
Command-line arguments:  -os macosx -ws cocoa -arch x86_64 -product org.eclipse.epp.package.java.product -clean -data /Users/patrik/workspace-akka

Error
Wed Feb 13 13:43:24 CET 2013
Error during askOption

java.lang.NullPointerException
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$addDefaultGetters$2$$anonfun$apply$15.apply(Namers.scala:1274)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$addDefaultGetters$2.apply(Namers.scala:1207)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$addDefaultGetters$2.apply(Namers.scala:1204)

@scabug
Copy link
Author

@scabug scabug commented Feb 13, 2013

@adriaanm said:
this seems to break a common scenario in the IDE, so I would consider fixing in the next RC, especially since we assumed it was fixed for 2.10.1

@scabug
Copy link
Author

@scabug scabug commented Feb 13, 2013

@lrytz said:
what does it mean "when switching branches"? do you know how to reproduce the error?

@scabug
Copy link
Author

@scabug scabug commented Feb 13, 2013

Patrik Nordwall (patriknw) said:
I don't know how to reproduce it but I mentioned that I often switch git branches, from command line, which triggers refresh in Eclipse. I could have done that when this happend, but I'm not sure.

@scabug
Copy link
Author

@scabug scabug commented Feb 19, 2013

@dragos said:
I don't think switching branches causes it, but it could play a role in timing. The scenario where this happens is roughly this sequence:

  • get tree right after namers (symbols are in the tree, but the tree is not yet typechecked)
  • traverse the tree and call sym.info along the way. This triggers lazy type completers, and one of them seems to assume a certain order of events

I couldn't reproduce this (yet) in a controlled environment, but I will try again.

@scabug
Copy link
Author

@scabug scabug commented Feb 19, 2013

@huitseeker said:
Had it this afternoon on 2.10.x 20ae01f4d86df1e33abaad76be171b596c8f39f3 (ping me for stacktrace).
No branch switch this time, but massive re-opening of editors by switching to a different Mylyn context.

@scabug
Copy link
Author

@scabug scabug commented Feb 19, 2013

@retronym said:
I've reenabled the null check, but added more logging here: scala/scala#2138

@scabug
Copy link
Author

@scabug scabug commented Feb 19, 2013

@dragos said:
I can reproduce it in the debugger (but no stand-alone test yet). All I need is a class that defines an annotation with a default parameter, this is enough:

class HippyAnnotation[T <: Throwable](cause: String = "") extends scala.annotation.StaticAnnotation {
  def this(clazz: Class[T]) = this()
}

It all boils down to this code in Namers.scala:

      // if default getters (for constructor defaults) need to be added to that module, here's the namer
      // to use. clazz is the ModuleClass. sourceModule works also for classes defined in methods.
      val module = clazz.sourceModule
      for (cda <- module.attachments.get[ConstructorDefaultsAttachment]) {
        cda.companionModuleClassNamer = templateNamer
      }

The sourceModule call assumes it will get something other than NoSymbol, but that's not the case: clazz is the class symbol for the annotation, and therefore does not have a moduleClass. It follows that the namer is not assigned to the attachment, that stays null.

@scabug
Copy link
Author

@scabug scabug commented Feb 19, 2013

@retronym said:
I still don't see what's different between an annotation and regular class here...

@scabug
Copy link
Author

@scabug scabug commented Feb 19, 2013

@dragos said:
True, I didn't minimize it all the way. Here it is, all that's needed to see it:

class HippyClass(cause: String = "")

@scabug
Copy link
Author

@scabug scabug commented Feb 19, 2013

@retronym said (edited on Feb 19, 2013 5:24:49 PM UTC):
Yep, the buggy code is only exercised for constructor parameter defaults, which must be generated in the companion object.

@scabug scabug closed this Feb 19, 2013
@scabug
Copy link
Author

@scabug scabug commented Dec 10, 2013

@huitseeker said (edited on Dec 10, 2013 2:18:38 PM UTC):
This probably manifested in the IDE as #1001479

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants