Skip to content

Try/hygienic desugaring #68

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

Closed
wants to merge 3 commits into from

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Mar 13, 2014

Desugaring is now hygienic.

Desugaring involves copying things in new scopes. Example: Constructor parameters of an implicit case class are copied to (1) the apply method in the companion object (2) the copy method in the class itself, (3) the implicit wrapper in the enclosing scope, and (4) type parameters are also copied to the unapply method in the companion object. It is important that the types of these parameters are all resolved in the same context as the constructor parameter. Otherwise name clashes can result, or, what's worse, things can be resolved in the wrong context. A particular bad case arises if an inner class inherits some generic instance of its outer class. In that case it makes a big difference whether something is resolved in the class or outside of it.

At the same time, we cannot simply copy full types, because the local copies might contain references to redefined type parameters and term parameters which need to be re-bound.

The present pull request achieves all that. And except for some general logic, it is local to Desugar, no cooperation of Namer or Typer is needed. As a bonus, we get a more principled treatment of getter parameters which does not require Namer cooperation.

odersky added 3 commits March 12, 2014 17:57
Adds a new scheme by which a TypeTree() can refer for its type to the symbol of some other type.
Applies the scheme to setter parameters, replacing the previous ad-hoc solution.
To get truly hygienic desugared trees, we need a derived type tree scheme that's more
flexible than just the previous two choices of info-of-symbol and typeref-of-symbol.
The new scheme based on DerivedTypeTrees allows arbitrary methods to derive the type tree's type.
Made desugaring hygienic. Trees that are derived from some other tree are no longer stored as simple
untyped Ident trees, but as TypeTrees that know how to derive their types from some other type.

Test cases in pos: hygiene.scala, t0054.scala and t0085.scala.

The comment in hygiene.scala points to the difficulties we are facing. In particular, we need type
trees that can rebind some references of a source type to local occurrences with the same name. t0054.scala is similar to hygiene.scala. t0085.scala is trickier, but also related. Essentially the problem there is that we have a class
that inherits its outer class. In this case it is important to resolve an identifier in the right context. The identifier added to the copy method of a case class must be resolved outside the class (just like the same
identifier in the constructor of that case class).
@odersky
Copy link
Contributor Author

odersky commented Mar 13, 2014

Review by @xeno-by @sjrd

@xeno-by
Copy link

xeno-by commented Mar 13, 2014

/cc @densh

*/
abstract class DerivedTypeTree extends TypeTree(EmptyTree) {

private var myWatched: Tree = EmptyTree
Copy link

Choose a reason for hiding this comment

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

Can we get away with copy on write instead of mutability here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's only used for diagnostics anyway. Could delete the field it, at the risk of less helpful debug output.

@sjrd
Copy link
Member

sjrd commented Mar 17, 2014

Otherwise LGTM

@@ -18,6 +18,7 @@ class tests extends CompilerTest {

val posDir = "./tests/pos/"
val negDir = "./tests/neg/"
val newDir = "./tests/new/"
Copy link

Choose a reason for hiding this comment

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

What does this mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a staging area for new tests. Should be empty normally. My workflow is the following:

  1. Pull in some tests to new
  2. Run new_all in tests.
  3. Triage into pos, invalid/pos, pending/pos, depending on test outcomes and bug fixes.

@gzm0
Copy link
Contributor

gzm0 commented Mar 21, 2014

@odersky can we close this in favor of #88?

@odersky
Copy link
Contributor Author

odersky commented Mar 21, 2014

@gzm0 Yes, let's close.

@odersky odersky closed this Mar 21, 2014
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.

6 participants