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

java.lang.InternalError: Malformed class name #5425

Closed
scabug opened this issue Jan 31, 2012 · 7 comments
Closed

java.lang.InternalError: Malformed class name #5425

scabug opened this issue Jan 31, 2012 · 7 comments
Assignees

Comments

@scabug
Copy link

scabug commented Jan 31, 2012

object Test extends App {
  {
    class A
    println(classOf[A].getSimpleName())
  }
}
Exception in thread "main" java.lang.InternalError: Malformed class name
	at java.lang.Class.getSimpleName(Class.java:1133)
	at Test$delayedInit$body.apply(t5256c.scala:4)
	at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
	at scala.App$$anonfun$main$1.apply(App.scala:61)
	at scala.App$$anonfun$main$1.apply(App.scala:61)
	at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
	at scala.collection.immutable.List.foreach(List.scala:77)
	at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:31)
	at scala.collection.mutable.ListBuffer.foreach(ListBuffer.scala:45)
	at scala.App$class.main(App.scala:61)
	at Test$.main(t5256c.scala:1)
	at Test.main(t5256c.scala)
@scabug
Copy link
Author

scabug commented Jan 31, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5425?orig=1
Reporter: @xeno-by
Affected Versions: 2.10.0
Duplicates #2034

@scabug
Copy link
Author

scabug commented Jan 31, 2012

@xeno-by said:

    public String getSimpleName() {
	if (isArray())
	    return getComponentType().getSimpleName()+"[]";

	String simpleName = getSimpleBinaryName();
	if (simpleName == null) { // top level class
	    simpleName = getName();
	    return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
	}
	// According to JLS3 "Binary Compatibility" (13.1) the binary
	// name of non-package classes (not top level) is the binary
	// name of the immediately enclosing class followed by a '$' followed by:
	// (for nested and inner classes): the simple name.
	// (for local classes): 1 or more digits followed by the simple name.
	// (for anonymous classes): 1 or more digits.

	// Since getSimpleBinaryName() will strip the binary name of
	// the immediatly enclosing class, we are now looking at a
	// string that matches the regular expression "\$[0-9]*"
	// followed by a simple name (considering the simple of an
	// anonymous class to be the empty string).

	// Remove leading "\$[0-9]*" from the name
	int length = simpleName.length();
	if (length < 1 || simpleName.charAt(0) != '$')
	    throw new InternalError("Malformed class name");
	int index = 1;
	while (index < length && isAsciiDigit(simpleName.charAt(index)))
	    index++;
	// Eventually, this is the empty string iff this is an anonymous class
	return simpleName.substring(index);
    }

classOf[A].getEnclosingClass().getName => "Test$"
classOf[A].getName => "Test$A$1"

Well, according to the source code of getSimpleName, A should be flattened into Test$$A$1. What's even more interesting, the correct name indeed appears after LambdaLift, but then gets messed by Flatten:

C:\Projects\Kepler\sandbox>scalac -Xprint:lambdalift,flatten t5425.scala
[[syntax trees at end of lambdalift]]// Scala source: t5425.scala
package <empty> {
  final object Test extends Object with App with ScalaObject {
    def <init>(): object Test = {
      Test.super.<init>();
      Test.this.$asInstanceOf[App$class]()./*App$class*/$init$();
      ()
    };
    {
      scala.this.Predef.println(classOf[Test$$A$1].getSimpleName())
    };
    class A$1 extends Object with ScalaObject {
      def <init>(): Test#A$1 = {
        A$1.super.<init>();
        ()
      }
    }
  }
}

[[syntax trees at end of flatten]]// Scala source: t5256c.scala
package <empty> {
  final object Test extends Object with App with ScalaObject {
    def <init>(): object Test = {
      Test.super.<init>();
      Test.this.$asInstanceOf[App$class]()./*App$class*/$init$();
      Test.this.delayedInit(new Test$delayedInit$body(Test.this));
      ()
    }
  };
  class Test$A$1 extends Object with ScalaObject {
    def <init>(): Test$A$1 = {
      Test$A$1.super.<init>();
      ()
    }
  };
  final <synthetic> class Test$delayedInit$body extends scala.runtime.AbstractFunction0 with ScalaObject {
    final def apply(): Object = {
      {
        scala.this.Predef.println(classOf[Test$A$1].getSimpleName())
      };
      scala.runtime.BoxedUnit.UNIT
    };
    def <init>($outer: object Test): Test$delayedInit$body = {
      Test$delayedInit$body.super.<init>();
      ()
    }
  }
}

@scabug
Copy link
Author

scabug commented Jan 31, 2012

@gkossakowski said:
This works:

object Test extends App {
  class A
  println(classOf[A].getSimpleName())
}

But this fails:

object Test extends App {
  object A {
    class B
  }
  println(classOf[A.B].getSimpleName())

for the same reason as Eugene stated. The first example works because we put A into 'Test' class and not 'Test$'. Note that class without dollar sign is generated only for top-level objects as a place where we can put static forwarders to object's method.

@scabug
Copy link
Author

scabug commented Jan 31, 2012

@paulp said:
Be sure to read all the comments in these tickets, there are a lot of them.

https://issues.scala-lang.org/secure/IssueNavigator.jspa?mode=hide&requestId=11004

@scabug
Copy link
Author

scabug commented Jan 31, 2012

@paulp said:
Oh, and keep in mind that the fucking jira conversion turned every '$' into '$$' and nobody ever fixed it.

@scabug
Copy link
Author

scabug commented Jan 31, 2012

@gkossakowski said:
Also, this is useful read: https://groups.google.com/d/topic/scala-internals/5ivpeZCfrW4/discussion

And we would keep the sun shining on this one: https://scala-webapps.epfl.ch/jenkins/view/Misc/job/scala-signatures/

It verifies problems mentioned in original thread do not come back.

@scabug
Copy link
Author

scabug commented Jan 31, 2012

@xeno-by said:
Duplicate of #2034

@scabug scabug closed this as completed Jan 31, 2012
hrhino added a commit to hrhino/shapeless that referenced this issue May 23, 2017
…t compile time. (milessabin#707)

Doesn't change behavior at all (other than that nested types which
previously triggered scala/bug#5425 now are printed like everything else),
but does plausibly increase efficiency slightly when large numbers of
calls to `.describe` are being made.
hrhino added a commit to hrhino/shapeless that referenced this issue May 23, 2017
…t compile time.

Doesn't change behavior at all (other than that nested types which
previously triggered scala/bug#5425 now are printed like everything else),
but does plausibly increase efficiency slightly when large numbers of
calls to `.describe` are being made.

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

No branches or pull requests

2 participants