Skip to content

use methods to find companion class #436

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

Merged
merged 23 commits into from
Apr 2, 2015

Conversation

DarkDimius
Copy link
Contributor

No description provided.

@DarkDimius
Copy link
Contributor Author

This branch includes change only to companionClass. I'll make a separate PR for companionModule when I implement it.

@DarkDimius DarkDimius force-pushed the linked-class branch 2 times, most recently from 034cce7 to 93399e7 Compare March 26, 2015 16:34
@DarkDimius
Copy link
Contributor Author

@odersky please review.

else if (defaultGetters.nonEmpty)
companionDefs(anyRef, defaultGetters)
else Nil
else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the change in formatting? I liked the old one better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was rewritten, it used to have more complicated logic between the commits. I have no problem changing it back.

@odersky
Copy link
Contributor

odersky commented Mar 28, 2015

I did not see a place where companion methods are turned into trees. Did I miss something? The concern here is that TreeTypeMap (and with it, subst, changeOwner) work on trees, not scopes. So they will not create new companion links unless the methods are part of the tree,

@DarkDimius
Copy link
Contributor Author

Actually due to way how TreeTypeMap works now, I'm not synthesizing the tree. It's not obvious what does it mean for companion links to TreeTypeMap the tree, which includes a class but doesn't include the companion. In this case we can end up with several classes that have the same companion module, eg in case of

case class C[@specialized T](a: T)

we'll have companion object which is same for all specialized classes.

I wanted to discuss if this is what we want. Actually the more i think of this, the more I believe that this actually makes sense.

if (companionClassMethod.exists)
companionClassMethod.entered
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a pity that we still need scalacLinkedClass here, because it means we cannot get rid of the associated complexity of isCoDefinedWith. I would much prefer if we got the linked class directly from the unpickling info, instead of looking at
the scope.

@odersky
Copy link
Contributor

odersky commented Mar 28, 2015

Overall, I am a bit ambivalent about this PR. It adds a lot of complications. So far the main benefit is that it makes linkedClass insensitive to naming issues. However, I would prefer simply to get naming right instead of inventing another mechanism to patch any faults it might have. And it looks that this (getting naming right) requires altogether less effort than this PR.

There would be a win in my mind if we could at the same time get rid of isCoDefinedWith which is fragile and very dependent on how the compiler is used. But so far the PR does not do that.

@DarkDimius
Copy link
Contributor Author

@odersky, can you please tell which complications you mean in your comment? All this pr does:

  1. Detects companion links using old scheme for Java and Scala2 defined classes.
  2. Adds companion links for dotty-defined classes during appropriate moment that doesn't break anything in typer.
  3. relies indeed currently relies on previous implementation, but if there's a simpler way to discover companion links, nothing stops us from using it.
  4. doesn't seem to add any complications, but actually revealed several bugs\deviations from what scalac does

@DarkDimius
Copy link
Contributor Author

So far the main benefit is that it makes linkedClass insensitive to naming issues. However, I would prefer simply to get naming right instead of inventing another mechanism to patch any faults it might have.

Yes, and it also gives us guarantees that any tool that somehow changes or interacts with TASTY files, or any compiler plugin, becomes easier to implement as there is one less thing that they can break: links between companions cannot be silently broken without intention anymore. I believe that this is an improvement on its own.

@odersky
Copy link
Contributor

odersky commented Mar 28, 2015

Regarding the TreeTypeMap issue, the problem is if you duplicate a code like this:

 def f() { class C { ... } object C { ... } ... }

I do not see how the link between the copies of the C's could be maintained.

@odersky
Copy link
Contributor

odersky commented Mar 28, 2015

Complications: I just look at (1) lines added, (2) files touched, and the pretty hairy code in Namer. It certainly looks like we cannot contain this to a single point, and have to add complications to several places.

Regarding robustness, I am still not sure. I am more of the school of "fail early". That is, if somebody gets naming wrong it's better to fail quickly rather than have another mechanism that works around it. Otherwise put, try to get to a state where every piece of information is encoded in exactly one way. One could argue that companion methods are what defines companionship and names do not matter. But then we need to (1) get rid of references where names do matter as in scalacLinkedClass and (2) make sure that names will never matter in any other way. If we fail to do that, it's probably better to make sure names work right, because that way we do not duplicate info and if we get it wrong we fail early.

But I noted another aspect where the new scheme beats the old: We no longer need to traverse the tree to find companions of inner classes. That's a big win! And furthermore, one could argue that scalac unpickling is the only reason we still need scalacLinkedClass, and hopefully that will go away and be replaced with TASTY. So that tilts the balance back in favor of this PR.

@DarkDimius
Copy link
Contributor Author

@odersky, in your example, are you TreeTypeMap-ing def f()? or only class C?
If first one(def f()), it should use the same mechanism that works for every method in class C that could return object C. I've tested and it just works(withMappedSyms in transformDefs handles this).

If you are duplicating class C inside f without duplicating object C we need to understand what does this mean for those links at all.

I propose to take this discussion offline, but it would help me if you could tell me what do you find complicated in this PR, as I will have time to address this comments and come up with simpler implementation.

The only complicated thing that I see around is scalacLinkedClass, which is not added but only maintained. It is only used to retrieve the information from scalac, if we had TASTY, it would no longer be needed.

@odersky
Copy link
Contributor

odersky commented Mar 28, 2015

I meant: duplicate def f. On second thought, I now see how this works. So much the better if we do not need the trees, since there's no code generated for them anyway.

@odersky
Copy link
Contributor

odersky commented Mar 28, 2015

Overall I am now in favor of the PR. I would try hard to find a better implementation in Namer, however.

There's a non-standard interaction between explicitOuter and Pattern matcher,
 as patmat can request outer symbols to be available earlier.
Note that this fix makes code between pattern matcher & explicitOuter non-Ycheck-able,
 as patmat adds reference to future symbol.
As private symbols aren't inherited, this does not break caching.
@odersky
Copy link
Contributor

odersky commented Mar 31, 2015

I've added the assertion, based on discussion that we had: if enter gets a scope as an argument, than
this is a scope that will eventually become decls of this symbol. And this should only happen if this is
first time the scope of symbol is coputed, ie symbol yet has no future.

OK, good! Then let's add this to the comment, to make it more understandable.

@odersky
Copy link
Contributor

odersky commented Mar 31, 2015

That's all I have.

DarkDimius added a commit to dotty-staging/dotty that referenced this pull request Apr 2, 2015
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

Successfully merging this pull request may close these issues.

3 participants