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

private vars need to be excluded consistently #33

Open
squito opened this issue Jan 10, 2014 · 3 comments
Open

private vars need to be excluded consistently #33

squito opened this issue Jan 10, 2014 · 3 comments

Comments

@squito
Copy link
Contributor

squito commented Jan 10, 2014

Excluding private does not work consistently right now. I have a feeling that its just not possible to do this correctly, because of the fact that we're looking at scala vars through java reflection. Which means we should just never try to exclude fields b/c they are private. (If we could consistently exclude private fields, then that would be better.)

Basically, it works for fields defined in a class, but not traits:

import com.quantifind.sumac.{Arg,FieldArgs,Ignore}

def hasX(a: FieldArgs): Boolean = {
  a.getArgs("").find{_.getName.endsWith("x")}.isDefined
}

trait Foo extends FieldArgs {
  private var x = 5
}
class Blah extends FieldArgs {
  private var x = 5
}
class Bippy extends Foo

hasX(new Foo{}) // true
hasX(new Blah()) // false
hasX(new Bipppy()) // true

I'm not sure if this was always broken, or if it happened with the upgrade to 2.10 and we didn't notice it, or if it was a code change. (I don't think it was a code change.)

@squito
Copy link
Contributor Author

squito commented Jan 10, 2014

After playing around a bit with different versions of scalac and then using javap, I'm pretty sure this never worked.

Given this file:

trait Foo {
  private var x = 5
  var y = 7
}

class Blah {
  private var x = 5
  var y = 7
}
class Bippy extends Foo

if you compile with scala 2.9.3, and then use javap -private ..., you'll see that Blah has a normal looking x:

Compiled from "blah.scala"
public class Blah extends java.lang.Object implements scala.ScalaObject{
    private int x;
    private int y;
    private int x();
    private void x_$eq(int);
    public int y();
    public void y_$eq(int);
    public Blah();
}

but Bippy has name mangling done to x (but not y!!):

public class Bippy extends java.lang.Object implements Foo{
    private int Foo$$x;
    private int y;
    public final int Foo$$x();
    public final void Foo$$x_$eq(int);
    public int y();
    public void y_$eq(int);
    public Bippy();
}

We could change the rule used for finding a name match here https://github.com/quantifind/Sumac/blob/master/core/src/main/scala/com/quantifind/sumac/FieldArgs.scala#L50 to check for something that endsWith "$$_$eq" instead, but I worry that will be brittle. I think I'd only be willing to make that change if we find it somewhere in the scala spec ...

@squito
Copy link
Contributor Author

squito commented Jan 10, 2014

actually, after a bit more thought, the name mangling makes perfect sense. private fields can have name clashes, but public ones can't. so maybe this is in the spec somewhere ...

@squito
Copy link
Contributor Author

squito commented Jan 15, 2014

Just deleted a comment that made no sense ...
The problem is not the name mangling. The problem is that the private var x in Bippy still somehow gets a public setter: public final void Foo$$x_$eq(int);. So I don't see any good way, from the view of java reflection, to figure out which vars are public & private in scala.

(I see that there is a final on the setter for x ... but unless I can see clear documentation in the spec that final is used in only these situations, I don't want to bank on it.)

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

1 participant