Skip to content

Assorted incremental compiler bug fixes.#2343

Merged
eed3si9n merged 12 commits into0.13from
topic/inc-comp-stable-self
Jan 7, 2016
Merged

Assorted incremental compiler bug fixes.#2343
eed3si9n merged 12 commits into0.13from
topic/inc-comp-stable-self

Conversation

@eed3si9n
Copy link
Member

Cherry picked adriaanm#1 on top of 0.13 to prepare for 0.13.10.

/cc @adriaanm

@lightbend-cla-validator

Hi @romanowski,

Thank you for your contribution! We really value the time you've taken to put this together.

Before we proceed with reviewing this pull request, please sign the Typesafe Contributors License Agreement:

http://www.typesafe.com/contribute/cla

@dwijnand
Copy link
Member

I know that this is WIP, but just wanted to mention, it would be great to have lots of notes about these assorted changes for the release.

@eed3si9n eed3si9n added this to the 0.13.10 milestone Dec 30, 2015
@eed3si9n
Copy link
Member Author

[error] (sbtRoot/*:scripted) Failed tests:
[error]     source-dependencies / value-class

eed3si9n referenced this pull request in adriaanm/sbt Dec 31, 2015
For refinement types, the Structure was already restricted
to declarations (and not inherited members), but all base types
were still included for a refinement's parents, which would
create unwieldy, and even erroneous (cyclic) types by expanding
all constituents of an intersection type to add all base types.

Since the logic already disregarded inherited members, it seems
logical to only include direct parents, and not all ancestor types.

Incremental compilation no longer includes a huge cyclic type,
and thus `ShowAPI` in principle does not need to deal with cycles,
but we'll keep that functionality in there for now.

```
class Dep {
  def bla(c: Boolean) = if (c) new Value else "bla"
}

class Value extends java.lang.Comparable[Value] { def compareTo(that: Value): Int = 1 }
```
adriaanm and others added 10 commits January 6, 2016 13:56
Call `initialize` in case symbol's `info` hadn't been completed
during normal compilation.

Also, normalize to the class symbol immediately.

Add a TODO regarding only looking at class symbols,
and thus ignoring the term symbol for objects,
as the corresponding class symbol has all the relevant info.
The only aspect of the self variable that's relevant for
incremental compilation is its explicitly declared type,
and only when it's different from the type of the class that declares it.

Technically, any self type that's a super type of the class could be ignored,
as it cannot affect external use (instantiation/subclassing) of the class.
Motivated because we want to make it more robust & configurable.
Original motivation was to diagnose a cyclic type representation,
likely due to an f-bounded existential type, as illustrated by the following:

```
class Dep {
  // The API representation for `bla`'s result type contains a cycle
  // (an existential's type variable's bound is the existential type itself)
  // This results in a stack overflow while showing the API diff.
  // Note that the actual result type in the compiler is not cyclic
  // (the f-bounded existential for Comparable is truncated)
  def bla(c: Boolean) = if (c) new Value else "bla"
}

class Value extends java.lang.Comparable[Value] { def compareTo(that: Value): Int = 1 }
```

Limit nesting (`-Dsbt.inc.apidiff.depth=N`, where N defaults to `2`),
and number of declarations shown for a class/structural type
(via `sbt.inc.apidiff.decls`, which defaults to `0` -- no limit).

Limiting nesting is crucial in keeping the size of api diffs of large programs
within a reasonable amount of RAM...

For example, compiling the Scala library, the API diff with nesting at `4`
exhausts 4G of RAM...
For refinement types, the Structure was already restricted
to declarations (and not inherited members), but all base types
were still included for a refinement's parents, which would
create unwieldy, and even erroneous (cyclic) types by expanding
all constituents of an intersection type to add all base types.

Since the logic already disregarded inherited members, it seems
logical to only include direct parents, and not all ancestor types.

```
class Dep {
  def bla(c: Boolean) = if (c) new Value else "bla"
}

class Value extends java.lang.Comparable[Value] { def compareTo(that: Value): Int = 1 }
```
Specialize two implementations for each value of the `inherit` boolean argument.
Also use a more direct way of distinguishing declared and inherited members.

backwards compat for source-dependencies/inherited-dependencies
Also a bit more complete: handle SelectFromTypeTree,
consider the self type an inheritance dependency,
and flatten any refinement types in inherited types,
to get to the symbols of their parents, instead of the
useless symbol of the refinement class.

Include inheritance dependencies in regular ones

Also, update test to reflect the self type is now seen as an inheritance dependency.

self types are local, so don't treat them like inherited types

note inheritanceSymbols dealiases, where allSymbols is constructed differently

fix NPE in source-dependencies/macro-annotation
Since pickled annotated types and symbols only mention
static annotations, whereas compilation from source
sees all annotations, we must explicitly filter annotations
in the API representation using the same criteria as the pickler,
so that we generate the same API when compiling from source
as when we're loading classfiles.
Further categorize debug output as api diff ([diff]), and
invalidation ([inv]). Since we log a ton of diagnostics,
make it a bit easier to find the relevant bits.
@eed3si9n eed3si9n force-pushed the topic/inc-comp-stable-self branch from a6c6e53 to 81786a2 Compare January 6, 2016 19:01
@lightbend-cla-validator
Copy link

Hi @romanowski,

Thank you for your contribution! We really value the time you've taken to put this together.

Before we proceed with reviewing this pull request, please sign the Typesafe Contributors License Agreement:

http://www.typesafe.com/contribute/cla

@eed3si9n eed3si9n changed the title (wip) Assorted incremental compiler bug fixes. Assorted incremental compiler bug fixes. Jan 6, 2016
@adriaanm
Copy link
Contributor

adriaanm commented Jan 7, 2016

Hey, @eed3si9n, thanks for turning this into a PR! When looking at the release notes, I noticed I hadn't cleaned up 0f61629's commit message yet. It probably wasn't clear what it's doing, and so it's not included in the notes, although we may want to.

We should probably also mention the changes to logging (are they ok for you?). For example, you can now limit nesting (-Dsbt.inc.apidiff.depth=N, where N defaults to 2), and number of declarations shown for a class/structural type (via sbt.inc.apidiff.decls, which defaults to 0 -- no limit).

I'm happy to do the rewording.

/cc @gkossakowski for some double checking of my changes & fixes.

@eed3si9n
Copy link
Member Author

eed3si9n commented Jan 7, 2016

@adriaanm I summarized it to "Fixes the tracking of self types in the incremental compiler." I'd be happy to take better wording on a one-liner summary of this change.

As per logging, I was a bit sad to see beautiful Show typeclass-based logging go, but I figured you had good reasons to turn it into the current imple. Especially towards sbt 1.0 modularization, I don't want to promise any internal behaviors of the incremental compiler (beyond that it compiles stuff), so I intentionally didn't mention anything about that one. These logs are more or less for sbt/zinc devs only, correct?

@adriaanm
Copy link
Contributor

adriaanm commented Jan 7, 2016

Correct, the logs are meant to simplify reporting bugs. Honestly, I'm stumped that someone like the implicit approach to logging -- it took me a long time to wrap my head around it 😵

Regarding 0f61629, this fixed a performance problem with the old traversal, which would visit the same AST multiple times (first with traverseTrees at 0f61629#diff-29aef71183363f225a8d6946a80cf619L149, then again using super.traverse a few lines later), causing blowups on big code bases. It also improves the precision by visiting a couple of AST nodes that were missed before.

@dwijnand
Copy link
Member

dwijnand commented Jan 7, 2016

Out of curiosity are these changes coming from use of sbt inside the scala repo, or something else?

@adriaanm
Copy link
Contributor

adriaanm commented Jan 7, 2016

No, we're battle testing it on a customer's MLoC code base ;-)

@lightbend-cla-validator
Copy link

Hi @romanowski,

Thank you for your contribution! We really value the time you've taken to put this together.

Before we proceed with reviewing this pull request, please sign the Typesafe Contributors License Agreement:

http://www.typesafe.com/contribute/cla

eed3si9n added a commit that referenced this pull request Jan 7, 2016
Assorted incremental compiler bug fixes.
@eed3si9n eed3si9n merged commit f9dc203 into 0.13 Jan 7, 2016
@eed3si9n eed3si9n deleted the topic/inc-comp-stable-self branch January 7, 2016 16:54
@eed3si9n eed3si9n mentioned this pull request Jan 7, 2016
7 tasks
@gkossakowski
Copy link
Contributor

I wish @adriaanm had a chance to clean up commits before merging. Notes for future archeologists:

  • the 5152405 fixed symptom (OOME due to gigantic list of collected symbols) but not the real bug that was fixed in 0f61629
  • the 0f61629 fixes exponential walk on trees which caused exponential number of symbols collected from trees and an OOME as a result. It fixes other things mentioned in the commit message
  • the 0f61629 claims that self types are considered as inheritance dependencies but the diff of DependencySpecification shows that they are treated as member ref. This is correct treatment because a changes to a self type do not affect type checking of classes that inherit from a given class, they only affect classes that want to instantiate the class and they refer to it by a member reference

In aggregate, changes to the source code look good to me.

@eed3si9n
Copy link
Member Author

eed3si9n commented Jan 8, 2016

Due to sbt's omission, we weren't running the unit tests on the compiler bridge, which @gkossakowski caught in #2357. On my machine the test that was changed now fails:

[info] x Extracted source dependencies from public members
[error]  Set('E, 'A, 'G, 'B, 'D) is not equal to Set('E, 'A, 'G, 'B, 'C, 'D) (DependencySpecification.scala:29)
[error] Expected: ...'B, '[C, ']D)
[error] Actual:   ...'B, '[]D)

This is consistent with earlier comment:

the 0f61629 claims that self types are considered as inheritance dependencies but the diff of DependencySpecification shows that they are treated as member ref.

@adriaanm
Copy link
Contributor

adriaanm commented Jan 8, 2016

Yeah, that was one of the mistakes that @gkossakowski pointed out in my original code during an over-the-shoulder review. I should have been quicker with fixing the commit messages and test...

@eed3si9n
Copy link
Member Author

eed3si9n commented Jan 8, 2016

I'd be happy to roll the commit history back before this got merged if you're up for fixing the commits etc.

@eed3si9n eed3si9n restored the topic/inc-comp-stable-self branch January 8, 2016 21:25
@adriaanm
Copy link
Contributor

adriaanm commented Jan 8, 2016

I had planned to improve my branch before submitting the PR anyway, so, yes, I'm happy to make the fixes next week. I'll leave it up to you whether you want to push --force to a public branch -- at scala/scala, we would revert the commit instead.

@gkossakowski
Copy link
Contributor

Unfortunately, I have rebased my development branch on top of 0.13 already.
I'd like to suggest we fix the test (PR coming) and move on keeping in mind a good lesson for future submissions.

@adriaanm
Copy link
Contributor

adriaanm commented Jan 8, 2016

+1, thanks @gkossakowski

@gkossakowski
Copy link
Contributor

I submitted a fix in #2358. I'll wait for Travis to validate the change.

@dwijnand dwijnand deleted the topic/inc-comp-stable-self branch January 16, 2016 21:28
Duhemm added a commit to sbt/zinc that referenced this pull request Jan 18, 2016
Duhemm added a commit to sbt/zinc that referenced this pull request Feb 22, 2016
eed3si9n pushed a commit to eed3si9n/scala that referenced this pull request May 14, 2019
lrytz pushed a commit to lrytz/scala that referenced this pull request Nov 5, 2019
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