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

Broken signature for inner case object surrounded by a parametrized class #4820

Closed
scabug opened this issue Jul 20, 2011 · 10 comments
Closed
Assignees

Comments

@scabug
Copy link

scabug commented Jul 20, 2011

Consider following code:

package test

abstract class Test[A] {
  
  case object Y
  
}

Before r25326, badsigs.sh would report following errors:

mac-grek:badsigs grek$ rm -rf classes/* && scalac -d classes/ Test.scala && ~/scala/badsigs/badsigs.sh `pwd`/classes
Cleaning up /Users/grek/scala/badsigs/badsigs_working_dir
Checking /Users/grek/tmp/badsigs/classes:
Running Main app (will generate Java files and run ecj)
----------
1. ERROR in /Users/grek/scala/badsigs/badsigs_working_dir/src/C0.java (at line 0)
	import test.Test$Y$;
	^
Inconsistent classfile encountered: The undefined type parameter A is referenced from within Test$Y$
----------
1 problem (1 error)

----------
1. ERROR in /Users/grek/scala/badsigs/badsigs_working_dir/src/C1.java (at line 0)
	import test.Test;
	^
The class file Test<A> contains a signature '()Ltest/Test<TA;>.Y;' ill-formed at position 18
----------
1 problem (1 error)

Found 2 errors

By updating compiler to r25326, we get a bit different signatures but still broken:

mac-grek:badsigs grek$ rm -rf classes/* && scalac -d classes/ Test.scala && ~/scala/badsigs/badsigs.sh `pwd`/classes
Cleaning up /Users/grek/scala/badsigs/badsigs_working_dir
Checking /Users/grek/tmp/badsigs/classes:
Running Main app (will generate Java files and run ecj)
----------
1. ERROR in /Users/grek/scala/badsigs/badsigs_working_dir/src/C0.java (at line 0)
	import test.Test$Y$;
	^
Inconsistent classfile encountered: The undefined type parameter A is referenced from within Test$Y$
----------
1 problem (1 error)

----------
1. ERROR in /Users/grek/scala/badsigs/badsigs_working_dir/src/C1.java (at line 0)
	import test.Test;
	^
The class file Test<A> contains a signature '()Ltest/Test<TA;>.Y$;' ill-formed at position 18
----------
1 problem (1 error)

Found 2 errors
@scabug
Copy link
Author

scabug commented Jul 20, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4820?orig=1
Reporter: @gkossakowski
See #4023

@scabug
Copy link
Author

scabug commented Jul 20, 2011

@gkossakowski said:
More interesting findings here. It turns out that it's broken for object (not case object) too. Thus the minimal test-case would be:

package test
abstract class Test[A] {
  object Y  
}

You'll get following errors:

mac-grek:badsigs grek$ rm -rf classes/* && scalac -d classes/ Test.scala && ~/scala/badsigs/badsigs.sh `pwd`/classes
Cleaning up /Users/grek/scala/badsigs/badsigs_working_dir
Checking /Users/grek/tmp/badsigs/classes:
Running Main app (will generate Java files and run ecj)
----------
1. ERROR in /Users/grek/scala/badsigs/badsigs_working_dir/src/C0.java (at line 0)
	import test.Test$Y$;
	^
Inconsistent classfile encountered: The undefined type parameter A is referenced from within Test$Y$
----------
1 problem (1 error)

----------
1. ERROR in /Users/grek/scala/badsigs/badsigs_working_dir/src/C1.java (at line 0)
	import test.Test;
	^
The class file Test<A> contains a signature '()Ltest/Test<TA;>.Y;' ill-formed at position 18
----------
1 problem (1 error)

Found 2 errors

However, if I use lazy val and inner class:

package test
abstract class Test[A] {  
  class Y
  lazy val Y = new Y
}

badsigs.sh doesn't report any problems. It turns out that signatures of accessor method Y are in both cases the same (and correct). It's InnerClasses attribute that's broken in first case (object Y is not reported as an inner class).

Diff of javap for both cases proves the point:

mac-grek:badsigs grek$ diff object_sig lazyval_sig 
[...]
>   InnerClass: 
>    public #3= #17 of #13; //Y=class test/Test$Y of class test/Test
[...]

@scabug
Copy link
Author

scabug commented Jul 22, 2011

@paulp said:
Trivia for 4820 fans: this ticket number is also the number of iulian's thesis.

http://library.epfl.ch/en/theses/?nr=4820

It's a sign from the heavens!

@scabug
Copy link
Author

scabug commented Jul 22, 2011

@gkossakowski said:
:-)

Do we have any progress on it?

@scabug
Copy link
Author

scabug commented Jul 22, 2011

@paulp said:
Yeah, I burned the entirety of wednesday on it. It is the name mangling chicken coming home to roost. I knew he was coming someday. I should have the situation summarized by our 8AM meeting.

@scabug
Copy link
Author

scabug commented Jul 22, 2011

@soc said:

"object Y is not reported as an inner class"

This sounds pretty much like the problem previously uncovered with java reflection and objects.

@scabug
Copy link
Author

scabug commented Sep 9, 2011

Commit Message Bot (anonymous) said:
(grek in r25639) Fix various InnerClasses bugs.

This commit fixes two major problems:

  1. InnerClasses table missed entries
    that would close the chain between
    nested and top-level class.

  2. In some situations, classes
    corresponding to objects would be
    not be reported in the InnerClasses
    table.

For details it's the best to check #4819, #4820 and
#4983.

First problem mentioned above was straightforward to
fix so I won't be going into details.

The second one deserves more attention. From now, classes
corresponding to objects are properly reported as inner
classes. Also, members (classes, objects) of objects are
reported as inner classes of classes corresponding to
objects.

There's one caveat though: top level objects get two
classes (regular and mirror). Members of top-level
objects are declared as inner classes of mirror class
and not regular one. The reason for that is to allow
importing them from Java. For example:

object A { class B }

will be compiled into following classes: A, A$, A$B.
If we declared A$B as inner class of A$ (regular class
for objects) then it would be impossible to import
B using "import A.B" or "import A$.B" constructs. The
reason for that is that Java compiler seems to blindly
put dollars instead of looking at InnerClasses attribute.

Since non-top-level objects don't have a mirror class
it's impossible to use the same solution. Thus, in case
like this:

object A { object B { class C } }

it's impossible to import C from Java. That's the tradeoff
for fixing other (more serious) problems. It's never been
possible to do that in a clean way so we are not making
situation worse.

As a nice consequence of this change, we get better way to
refer to inner members of top-level objects. It's been
reflected in one of test-cases that is updated by this
change.

Fixes #4789 #4819 #4820 #4983 and possibly some
other tickets related to reflection.

Review by extempore, dragos.

@scabug
Copy link
Author

scabug commented Feb 20, 2012

@soc said:
Judging from the last commit message it seems like this one should be closed, but it isn't.

I ran the badsigs tool and it doesn't report any errors:

Root is /home/soc/Entwicklung/badsigs
Working dir is /tmp/badsigs.VG0Ed
Checking /home/soc/Entwicklung/badsigs/./classes/:
Running Main app (will generate Java files and run ecj)

I guess this can be closed?

@scabug
Copy link
Author

scabug commented May 7, 2012

@heathermiller said:
Judging by the conversation, the resulting commit, and the fact that all seems to build and run:

Heathers-iMac:scala-heather hmiller$ ../badsigs/badsigs.sh ../scala-heather/classes
Root is /Users/hmiller/Dropbox/git-shared/badsigs
Working dir is /tmp/badsigs.vsQMC
Badsigs JAR is /Users/hmiller/Dropbox/git-shared/badsigs/target/badsigs-assembly-0.1-SNAPSHOT.jar
Checking /Users/hmiller/Dropbox/git-shared/badsigs/../scala-heather/classes:
Running Main app (will generate Java files and run ecj)
Heathers-iMac:scala-heather hmiller$ 

All seems resolved, so I'll be closing this.

@scabug scabug closed this as completed May 7, 2012
@scabug
Copy link
Author

scabug commented May 7, 2012

@gkossakowski said:
Yes, it's fixed. I forgot to close it. Thanks Heather!

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