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

zinc's handling of As Seen From #174

Closed
gkossakowski opened this Issue Sep 14, 2016 · 3 comments

Comments

Projects
None yet
5 participants
@gkossakowski
Contributor

gkossakowski commented Sep 14, 2016

This issue discusses how Scala's prefix-dependent typing challanges incremental compilation as implemented by zinc. The resolution of path-dependent types is defined as an algorithm called As Seen From (ASF). At its core, ASF's concern is how type information flows between signatures of class members. A detailed description of the rules of ASF can be found here.

I'm assuming you're familiar with the basics of implementation of the incremental compiler. In order to follow the rest of this ticket, you need to understand how both API extraction and name hashing works.

Introduction

To illustrate the challanges of resolving class member signatures, let's consider an example where type members and inheritance are involved:

// A.scala
abstract class A {
  type T
  def foo(x: T): T = x
}
// B.scala
object B extends A {
  type T = Int
}
// C.scala
object C {
  val y: Int = B.foo(12)
}

Let's see what happens when a change (by a programmer) is made so T = Int in B becomes T = String. The incremental compiler will recompile B.scala and then it will analyze dependencies on B to figure out whether any other file require recompilation. The object C depends on B due to expression B.foo(12). However, we only see dependency on foo defined in A and no direct dependency on T. The naive incremental compilation algorithm would stop here by concluding that the change to T is not affecting C.

However, we see that after the change to T = String, the method foo takes String as an argument but the program passes the integer 12 as an argument. The problem is that we need to somehow capture the dependency on type member T of the method foo. Below we discuss how this dependency has been captured in the past and what kind of issues arise in more advanced scenarios.

Inheritance expansion

In this chapter I describe how the problem with capturing dependency on type parameter is implemented in sbt 0.13.

One way to capture dependency of the method foo on the type parameter T is to inline what we know about T into foo's signature whenever T is refined. Given that the type member T declared in A can be refined by any class inheriting inheriting from A, the inlining must happen for every class that inherits from A. For example, B inherits from A so zinc would copy foo from A to B and inline information about T as declared in B. From zinc's point of view, the API of B becomes:

object B extends A {
  type T = Int
  <inherited> def foo(x: Int): Int = x
}

Let's consider again the change of the type member from T = Int to T = String. Zinc would recompile B and see an updated signature of the inherited method foo with information about type member T inlined. This would cause C to be recompiled because B.foo(12) now have a dependency on the method foo defined in the object B.

To recap, the trick of tracking dependency on type members from other signatures is to copy the inherited members and inline type information known at this particular point of inheritance relation.

The advantage of inheritance expansion is that type member resolution is offloaded to ASF algorithm implemented by Scala compiler. All zinc needs to do is to ask for each member of a given class for its signature as seen from that class. The complicated job chasing down definitions and inlining the right information (e.g. looking at upper bounds) is implemented by the core of Scala's typechecking algorithm. This way, understanding how given change made by user affects other parts of the program is simple: you just calculate the entire set of members in a class and compare them member by member looking for differences in signatures. When performing comparison, all information about member's signature is inlined already.

The disadvantage of inheritance expansion is that API extraction algorithm has complexity O(n^2) where n is the depth of inheritance for a single inheritance chain. Very often, API extraction would waste time copying members whose signatures look exactly the same at every level of inheritance. The API extraction, as implemented in sbt 0.13, doesn't have any optimization for members that do not depend on other type members. Implementing such optimization is tricky because one has to almost run the whole ASF algorithm to understand whether a given member is dependent on any other member.

Wrong prefix

The scheme of inheritance expansion has a flaw in its implementation. To see the problem, let's consider an example that involves nested classes in addition to inheritance we considered above:

// A.scala
abstract class A {
  type T
  object X {
    def foo(x: T): T = x
  }
}
// B.scala
class B extends A {
  type T = Int
}
// C.scala
object C extends B
// D.scala
object D {
  C.X.foo(12)
}

There are two differences compared to our original example:

  1. The method foo is now declared in the nested object X
  2. There's one more level of inheritance: C inherits from B and we access the method X.foo through the object C instead of the class B

The additional level of inheritance is there due to technical details of how zinc's invalidation algorithm is implemented but it's not essential for illustration of the problem with the wrong prefix. The additional level of nesting through X is the essential part.

If we repaly the scenario considered earlier of changing defintion of the type member T = Int to T = String, we get no compilation error prior to sbt 0.13.12. The problem is with using the wrong prefix when extracting API of nested members. When Extract API starts processing the inherited member X while indexing B, it forgets to look at the method foo from B.this.X prefix and uses A.this.X prefix instead. Extract API always see the same signature foo(T)T regardless of what outer class defines as T; there's no inlining being done. It's a bug in the implementation of Extract API but a serious one. It means that we pay the O(n^2) cost of extracting APIs but get zero return as soon as nested classes are involved. The bug itself appears to be pretty hard to fix because Extract API works with symbols for prefixes but should use types instead. This is a design flaw and would require significant changes to the implementation of the entire Extract API logic.

Surprisingly, this example works as expected in sbt 0.13.12. The reason will be clear once I describe the changes applied to zinc 1.0 that were later backported to sbt 0.13.12.

Use-site expansion

The previous chapter described the strategy of capturing type information flow by copying members along inheritance axis and inlining everything known at the given point of inheritance chain. The algorithm described above works at granurality of a single class. This chapter will describe an alternative design that deals with capturing type information flow.

Let's look at the original example:

// A.scala
abstract class A {
  type T
  def foo(x: T): T = x
}
// B.scala
object B extends A {
  type T = Int
}
// C.scala
object C {
  val y: Int = B.foo(12)
}

We would like to capture the dependency on the type member T, as defined in the object B, in the expression B.foo(12). If think of type-checking as a form of annotating programs, the dependency detection becomes trivial. The annotated version of the expression B.foo(12) is:

B.((T = Int));(T = Int)::foo(12)

I'm using (param list);returnType:: to describe the resolved signatures. I left the typealias T = Int unexpanded so both dependency on the type member T and its right hand side Int can be captured.

The resolved signatures are created by Scala's typechecker. Zinc's job is to simply traverse the signatures and collect dependencies (and used names for name hashing). This approach is called use-site expansion because we expand signature of a member at the point where it's being used. The use-site expansion is implemented in zinc 1.0 and there's no expansion inheritance expansion performed.

The essential piece of use-site expansion has been backported to sbt 0.13.12 in this pull request. The original motivation for the backport was to fix handling of value classes.

Let's compare the inheritance expansion and the use-site expansion. The big advantage of the inheritance expansion approach is it's conceptual simplicity. ASF operates along two axes: nesting and inheritance. Nesting is easy to take care of because classes can be nested within classes declared in the same compilation unit (file). Making sure that information flows properly along nesting axis is trivial: outer and inner classes are recompiled at the same time. Since we look at nested members at every point of inheritance chain, it's easy to see that type information along inheritance axis is fully captured.

When it comes to performance, use-site expansion has the advantage of making Extract API simpler and cheaper: we only look at declarations in classes. The API extraction becomes a simple O(n) algorithm. However, dependency extraction becomes more difficult and expensive because we not only look at symbols of methods but we have to consider their types to see their full signatures. It's more work to traverse full types of called members.

However, use-site expansion seems to me to strike the right balance: both the api extraction and the dependency extraction have cost linear to the size of the program. With some caching strategies, I'm pretty sure one could make looking at signatures pretty fast.

Limitation of use-site expansion

There's a challange of making sure that signatures do actually capture all necessary information. This is illustrated by a test case submitted as a pending scripted test to zinc. The code below expands the example from the beginning of the chapter by introducing an upper bound S to the type member T. The code below simplifies signature of the method foo by just making it return a value:

// A.scala
abstract class A {
  type T <: S
  type S
  object X {
    def foo: T = null.asInstanceOf[T]
  }
}
// B.scala
class B extends A {
  type S <: Int
}
// C.scala
object C extends B
// D.scala
object D {
  val x: Int = C.X.foo
}

The challange is that signature of the method foo after type-checking, as indexed by zinc, doesn't include information about the upper bound of S. The signature of method foo in C.X.foo indexed by zinc is:

C.X.();(T)::foo

The missing information about bound introduced by the type member S causes zinc to not recompile the object D when the bound S is changed in the class B. This is the reason why the test case is added as pending

Plugging in holes in signature capture

In order to capture all necessary information of the signature, zinc would need to transitively include upper bounds so the signature becomes:

C.X.();(T <: S <: Int)::foo

In general case, both lower and upper bounds would need to be included transitively.

However, Scala supports F-bounded polymorphism so transitive expansion needs to take care of infinite expansion. For example, Scala allows the following bound to be declared:

object Outer {
  class A[T]
  type X <: A[X]
}

Without care, one might expand the upper bound into A[A[A[A...]]]. The upper bound is an arbitrary type so it can be a structural type (with its own type members) or a type constructor. It feels that expanded signatures can get out of hand pretty quickly. However, exactly the same issues arise in inheritance expansion and the Extract API already includes mechanisms for detecting and approximating recursive types. Also, the HashAPI class deals with recursive types.

In all examples above type members were used. The same analysis should be done for type parameters and similar conclusions would be reached as for type members. That is: zinc has to index type parameters (and their bounds) that appear in signatures of members referenced in a given file.

We do not stop at type members and type parameters. Paths need to be indexed too. Let's this with a modified version of the original example that used type member T. Here, we replace the type member with a value member t and refer to it in a path:

// A.scala
abstract class A {
  val t: Any
  object X {
    def foo: t.type = t
  }
}
// B.scala
class B extends A {
  val t: String = "abc"
}

When the signature of method foo is indexed at use sites, it should include information about the type of the val t defined in the object B. Vals can refer to other vals so indexing should be done transitively.

Summary

We discussed above the challange of capturing type information flow as dictated by Scala's As Seen From algorithm. The two approaches has been explored of how to deal with the type information flow along inheritance axis:

  • inheritance expansion where members are copied and the type information available at a given point in inheritance chain is inlined into members' signatures
  • use site expansion where signatures are indexed at the point where members are used and all available type information is inlined into signatures

For performance and correctness reasons it seems like use site expansion is a better approach. The use site expansion has been partially implemented in zinc 1.0 but indexing is not done transitively and not all types are captured.

One has to consider all types that can be referred in members' signatures and index all of them. The indexing has to be done transitively; the transitive closure should include only types (and paths, etc.) that are prefix-dependent and stop as soon as we see a type that is always seen the same (e.g. a type reference to a top-level class). In other words, we should index enough to capture all information that affects the outcome of running As Seen From algorithm which includes:

  • type parameters
  • existential types
  • the this (through which both type members and path segments are resolved)
@smarter

This comment has been minimized.

Show comment
Hide comment
@smarter

smarter Sep 14, 2016

Contributor

Great summary! See also the implementation of incremental compilation with use-site expansion in dotty, in particular see usedTypeTraverser that records used types with caching to avoid infinite loops.

I'm reasonably confident that the sbt phases from dotty could be backported to work with scalac without too much effort (they don't use much dotty-specific data structures like Denotation). However, they depend on sbt 0.13 so would need to be adapted for sbt/zinc 1.0.

Contributor

smarter commented Sep 14, 2016

Great summary! See also the implementation of incremental compilation with use-site expansion in dotty, in particular see usedTypeTraverser that records used types with caching to avoid infinite loops.

I'm reasonably confident that the sbt phases from dotty could be backported to work with scalac without too much effort (they don't use much dotty-specific data structures like Denotation). However, they depend on sbt 0.13 so would need to be adapted for sbt/zinc 1.0.

@jvican

This comment has been minimized.

Show comment
Hide comment
@jvican

jvican Feb 20, 2017

Member

I have a fix for this that I will submit in the next hours. First, I need to backport some of the changes that we did to Scala 2.11 sources to 2.10.

Member

jvican commented Feb 20, 2017

I have a fix for this that I will submit in the next hours. First, I need to backport some of the changes that we did to Scala 2.11 sources to 2.10.

@dwijnand

This comment has been minimized.

Show comment
Hide comment
@dwijnand

dwijnand Feb 23, 2017

Member

Exciting stuff @jvican. I'll unblock you on that back-porting first thing tomorrow.

Member

dwijnand commented Feb 23, 2017

Exciting stuff @jvican. I'll unblock you on that back-porting first thing tomorrow.

jvican added a commit to scalacenter/zinc that referenced this issue Feb 25, 2017

Fix sbt#174: Register names for types and symbols
The following commit fixes the issues with as seen from that are
explained in this fantastic issue by Greg: sbt#174.

These issues are related to the fact that our previous approach was only
inspecting types, when some type information like type bounds is only
present in symbols. To get that information, we need a more precise
search that looks into the core of the Scalac types for the required
information.

Of course, type bounds is not all we're interested about. The issue is
that type members, method parameters and type parameters can have type
information in its definition that is necessary at the use site to
detect and propagate changes. This information is also tied to the fact
that type members can have different materializations depending on the
prefix (both because of type members and path-dependent types).

`types-in-used-names-b` and `as-seen-from-b` are a perfect example of
this. This commit turns them into passing tests.

Having more in-depth look at the algorithm behind it will help us
understand what it does. In essence, the new type traverser is the
responsible of adding dependencies on every `TypeRef` and `SingleType`.
They contain concrete information about types (they are materialized),
so their presence must be recorded.

We also have the presence of other types like `PolyType` and
`MethodType`. These types are used for defining type parameters for
classes (think List[A]) and method type parameters (think def foo[T](t:
T)). They are nested, meaning that their return type can also be a
`PolyType` or a `MethodType`. To handle them, we traverse the symbols in
their definition -- for method types we traverse the types of the
parameters, while for poly types we add directly the dependency on the
symbol --so that the name of the type parameters are also recorded-- and
then we continue checking for their information if they are not a class,
that is, if they are an abstract type with a definition that we may need
to traverse (existential type, refined type, bounds, etc).

In the case of `TypeBounds`, we traverse them if they are not the
default specified by the SLS (`Nothing` for low bound, `Any` for high).

Refined types need special handling since we need to check their
declarations, that can introduce new type members or vals. If they do
have them, we add a dependency right away on those definitions.

As usual, `ThisType` and `ConstantType` need to be inspected by checking
their underlying representation (`C` in `C.this` and `12` in `Int(12)`).

`ExistentialType`, the last type on the traverser before falling back to
`mapOver`, has a list of symbols called `quantified` that needs to be
traversed since they are the symbol information that constrain the
existential type. As in the case of `TypeBounds`, we guard against the
default types `Nothing` for low bound and `Any` for high bound, so that
unnecessary names that are always present in source files don't appear.

jvican added a commit to scalacenter/zinc that referenced this issue Feb 26, 2017

Fix sbt#174: Register names for types and symbols
The following commit fixes the issues with as seen from that are
explained in this fantastic issue by Greg: sbt#174.

These issues are related to the fact that our previous approach was only
inspecting types, when some type information like type bounds is only
present in symbols. To get that information, we need a more precise
search that looks into the core of the Scalac types for the required
information.

Of course, type bounds is not all we're interested about. The issue is
that type members, method parameters and type parameters can have type
information in its definition that is necessary at the use site to
detect and propagate changes. This information is also tied to the fact
that type members can have different materializations depending on the
prefix (both because of type members and path-dependent types).

`types-in-used-names-b` and `as-seen-from-b` are a perfect example of
this. This commit turns them into passing tests.

Having more in-depth look at the algorithm behind it will help us
understand what it does. In essence, the new type traverser is the
responsible of adding dependencies on every `TypeRef` and `SingleType`.
They contain concrete information about types (they are materialized),
so their presence must be recorded.

We also have the presence of other types like `PolyType` and
`MethodType`. These types are used for defining type parameters for
classes (think List[A]) and method type parameters (think def foo[T](t:
T)). They are nested, meaning that their return type can also be a
`PolyType` or a `MethodType`. To handle them, we traverse the symbols in
their definition -- for method types we traverse the types of the
parameters, while for poly types we add directly the dependency on the
symbol --so that the name of the type parameters are also recorded-- and
then we continue checking for their information if they are not a class,
that is, if they are an abstract type with a definition that we may need
to traverse (existential type, refined type, bounds, etc).

In the case of `TypeBounds`, we traverse them if they are not the
default specified by the SLS (`Nothing` for low bound, `Any` for high).

Refined types need special handling since we need to check their
declarations, that can introduce new type members or vals. If they do
have them, we add a dependency right away on those definitions.

As usual, `ThisType` and `ConstantType` need to be inspected by checking
their underlying representation (`C` in `C.this` and `12` in `Int(12)`).

`ExistentialType`, the last type on the traverser before falling back to
`mapOver`, has a list of symbols called `quantified` that needs to be
traversed since they are the symbol information that constrain the
existential type. As in the case of `TypeBounds`, we guard against the
default types `Nothing` for low bound and `Any` for high bound, so that
unnecessary names that are always present in source files don't appear.

This change triggers a very weird behaviour in 2.10, in which for some
reason the names `Nothing` and `Any` appear. This does not seem to come
from the new TypeDependencyTraverser and I've been able to track its
appearance to the case in the traverser where we check for `hasSymbol`
and add with `addSymbol`. I've added a TODO, which is not urgent, to
find out what's happening, since this only affect one concrete snippet
of the whole test code.

Benchmark:

```
[info] # Run complete. Total time: 00:25:51
[info]
[info] Benchmark                                                            (_tempDir)    Mode  Cnt           Score            Error   Units
[info] HotScalacBenchmark.compile                                    /tmp/sbt_abdb5ed2  sample   18       20893.226 ±        625.622   ms/op
[info] HotScalacBenchmark.compile:compile·p0.00                      /tmp/sbt_abdb5ed2  sample            19797.115                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.50                      /tmp/sbt_abdb5ed2  sample            21005.074                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.90                      /tmp/sbt_abdb5ed2  sample            21894.267                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.95                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.99                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.999                     /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.9999                    /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p1.00                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:·gc.alloc.rate                     /tmp/sbt_abdb5ed2  sample   18         289.838 ±          8.669  MB/sec
[info] HotScalacBenchmark.compile:·gc.alloc.rate.norm                /tmp/sbt_abdb5ed2  sample   18  6500730176.000 ±   13633760.029    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space            /tmp/sbt_abdb5ed2  sample   18         289.082 ±         24.260  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm       /tmp/sbt_abdb5ed2  sample   18  6480403569.778 ±  464987965.594    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen               /tmp/sbt_abdb5ed2  sample   18          12.679 ±         12.697  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm          /tmp/sbt_abdb5ed2  sample   18   290767194.667 ±  290528363.065    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space        /tmp/sbt_abdb5ed2  sample   18           7.321 ±          2.865  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm   /tmp/sbt_abdb5ed2  sample   18   165547052.444 ±   66661097.019    B/op
[info] HotScalacBenchmark.compile:·gc.count                          /tmp/sbt_abdb5ed2  sample   18         101.000                   counts
[info] HotScalacBenchmark.compile:·gc.time                           /tmp/sbt_abdb5ed2  sample   18       21332.000                       ms
[info] WarmScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2  sample    3       52769.937 ±       6743.004   ms/op
[info] WarmScalacBenchmark.compile:compile·p0.00                     /tmp/sbt_abdb5ed2  sample            52412.023                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.50                     /tmp/sbt_abdb5ed2  sample            52747.567                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.90                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.95                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.99                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.999                    /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.9999                   /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p1.00                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2  sample    3         125.382 ±         13.840  MB/sec
[info] WarmScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2  sample    3  7055970890.667 ± 1078954896.900    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2  sample    3         117.215 ±         73.864  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2  sample    3  6596470733.333 ± 4281843293.325    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2  sample    3           2.279 ±          1.015  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2  sample    3   128269752.000 ±   72721263.065    B/op
[info] WarmScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2  sample    3          73.000                   counts
[info] WarmScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2  sample    3        8746.000                       ms
[info] ColdScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2      ss   10       44611.286 ±        963.131   ms/op
[info] ColdScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2      ss   10         152.054 ±          2.753  MB/sec
[info] ColdScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2      ss   10  7249761568.800 ±   95126804.264    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2      ss   10         144.481 ±          9.964  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2      ss   10  6889406191.200 ±  490961958.245    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen              /tmp/sbt_abdb5ed2      ss   10          ≈ 10⁻³                   MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm         /tmp/sbt_abdb5ed2      ss   10       21136.000 ±     101049.368    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2      ss   10           2.848 ±          0.335  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2      ss   10   135792956.800 ±   16291050.509    B/op
[info] ColdScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2      ss   10         248.000                   counts
[info] ColdScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2      ss   10       29901.000                       ms
[success] Total time: 1553 s, completed Feb 26, 2017 3:06:29 AM
[success] Total time: 0 s, completed Feb 26, 2017 3:06:29 AM
```

jvican added a commit to scalacenter/zinc that referenced this issue Feb 26, 2017

Fix sbt#174: Register names for types and symbols
The following commit fixes the issues with as seen from that are
explained in this fantastic issue by Greg: sbt#174.

These issues are related to the fact that our previous approach was only
inspecting types, when some type information like type bounds is only
present in symbols. To get that information, we need a more precise
search that looks into the core of the Scalac types for the required
information.

Of course, type bounds is not all we're interested about. The issue is
that type members, method parameters and type parameters can have type
information in its definition that is necessary at the use site to
detect and propagate changes. This information is also tied to the fact
that type members can have different materializations depending on the
prefix (both because of type members and path-dependent types).

`types-in-used-names-b` and `as-seen-from-b` are a perfect example of
this. This commit turns them into passing tests.

Having more in-depth look at the algorithm behind it will help us
understand what it does. In essence, the new type traverser is the
responsible of adding dependencies on every `TypeRef` and `SingleType`.
They contain concrete information about types (they are materialized),
so their presence must be recorded.

We also have the presence of other types like `PolyType` and
`MethodType`. These types are used for defining type parameters for
classes (think List[A]) and method type parameters (think def foo[T](t:
T)). They are nested, meaning that their return type can also be a
`PolyType` or a `MethodType`. To handle them, we traverse the symbols in
their definition -- for method types we traverse the types of the
parameters, while for poly types we add directly the dependency on the
symbol --so that the name of the type parameters are also recorded-- and
then we continue checking for their information if they are not a class,
that is, if they are an abstract type with a definition that we may need
to traverse (existential type, refined type, bounds, etc).

In the case of `TypeBounds`, we traverse them if they are not the
default specified by the SLS (`Nothing` for low bound, `Any` for high).

Refined types need special handling since we need to check their
declarations, that can introduce new type members or vals. If they do
have them, we add a dependency right away on those definitions.

As usual, `ThisType` and `ConstantType` need to be inspected by checking
their underlying representation (`C` in `C.this` and `12` in `Int(12)`).

`ExistentialType`, the last type on the traverser before falling back to
`mapOver`, has a list of symbols called `quantified` that needs to be
traversed since they are the symbol information that constrain the
existential type. As in the case of `TypeBounds`, we guard against the
default types `Nothing` for low bound and `Any` for high bound, so that
unnecessary names that are always present in source files don't appear.

This change triggers a very weird behaviour in 2.10, in which for some
reason the names `Nothing` and `Any` appear. This does not seem to come
from the new TypeDependencyTraverser and I've been able to track its
appearance to the case in the traverser where we check for `hasSymbol`
and add with `addSymbol`. I've added a TODO, which is not urgent, to
find out what's happening, since this only affect one concrete snippet
of the whole test code.

Benchmark:

```
[info] # Run complete. Total time: 00:25:51
[info]
[info] Benchmark                                                            (_tempDir)    Mode  Cnt           Score            Error   Units
[info] HotScalacBenchmark.compile                                    /tmp/sbt_abdb5ed2  sample   18       20893.226 ±        625.622   ms/op
[info] HotScalacBenchmark.compile:compile·p0.00                      /tmp/sbt_abdb5ed2  sample            19797.115                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.50                      /tmp/sbt_abdb5ed2  sample            21005.074                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.90                      /tmp/sbt_abdb5ed2  sample            21894.267                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.95                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.99                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.999                     /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.9999                    /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p1.00                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:·gc.alloc.rate                     /tmp/sbt_abdb5ed2  sample   18         289.838 ±          8.669  MB/sec
[info] HotScalacBenchmark.compile:·gc.alloc.rate.norm                /tmp/sbt_abdb5ed2  sample   18  6500730176.000 ±   13633760.029    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space            /tmp/sbt_abdb5ed2  sample   18         289.082 ±         24.260  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm       /tmp/sbt_abdb5ed2  sample   18  6480403569.778 ±  464987965.594    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen               /tmp/sbt_abdb5ed2  sample   18          12.679 ±         12.697  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm          /tmp/sbt_abdb5ed2  sample   18   290767194.667 ±  290528363.065    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space        /tmp/sbt_abdb5ed2  sample   18           7.321 ±          2.865  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm   /tmp/sbt_abdb5ed2  sample   18   165547052.444 ±   66661097.019    B/op
[info] HotScalacBenchmark.compile:·gc.count                          /tmp/sbt_abdb5ed2  sample   18         101.000                   counts
[info] HotScalacBenchmark.compile:·gc.time                           /tmp/sbt_abdb5ed2  sample   18       21332.000                       ms
[info] WarmScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2  sample    3       52769.937 ±       6743.004   ms/op
[info] WarmScalacBenchmark.compile:compile·p0.00                     /tmp/sbt_abdb5ed2  sample            52412.023                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.50                     /tmp/sbt_abdb5ed2  sample            52747.567                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.90                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.95                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.99                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.999                    /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.9999                   /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p1.00                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2  sample    3         125.382 ±         13.840  MB/sec
[info] WarmScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2  sample    3  7055970890.667 ± 1078954896.900    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2  sample    3         117.215 ±         73.864  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2  sample    3  6596470733.333 ± 4281843293.325    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2  sample    3           2.279 ±          1.015  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2  sample    3   128269752.000 ±   72721263.065    B/op
[info] WarmScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2  sample    3          73.000                   counts
[info] WarmScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2  sample    3        8746.000                       ms
[info] ColdScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2      ss   10       44611.286 ±        963.131   ms/op
[info] ColdScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2      ss   10         152.054 ±          2.753  MB/sec
[info] ColdScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2      ss   10  7249761568.800 ±   95126804.264    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2      ss   10         144.481 ±          9.964  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2      ss   10  6889406191.200 ±  490961958.245    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen              /tmp/sbt_abdb5ed2      ss   10          ≈ 10⁻³                   MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm         /tmp/sbt_abdb5ed2      ss   10       21136.000 ±     101049.368    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2      ss   10           2.848 ±          0.335  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2      ss   10   135792956.800 ±   16291050.509    B/op
[info] ColdScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2      ss   10         248.000                   counts
[info] ColdScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2      ss   10       29901.000                       ms
[success] Total time: 1553 s, completed Feb 26, 2017 3:06:29 AM
[success] Total time: 0 s, completed Feb 26, 2017 3:06:29 AM
```

jvican added a commit to scalacenter/zinc that referenced this issue Feb 26, 2017

Fix sbt#174: Register names for types and symbols
The following commit fixes the issues with as seen from that are
explained in this fantastic issue by Greg: sbt#174.

These issues are related to the fact that our previous approach was only
inspecting types, when some type information like type bounds is only
present in symbols. To get that information, we need a more precise
search that looks into the core of the Scalac types for the required
information.

Of course, type bounds is not all we're interested about. The issue is
that type members, method parameters and type parameters can have type
information in its definition that is necessary at the use site to
detect and propagate changes. This information is also tied to the fact
that type members can have different materializations depending on the
prefix (both because of type members and path-dependent types).

`types-in-used-names-b` and `as-seen-from-b` are a perfect example of
this. This commit turns them into passing tests.

Having more in-depth look at the algorithm behind it will help us
understand what it does. In essence, the new type traverser is the
responsible of adding dependencies on every `TypeRef` and `SingleType`.
They contain concrete information about types (they are materialized),
so their presence must be recorded.

We also have the presence of other types like `PolyType` and
`MethodType`. These types are used for defining type parameters for
classes (think List[A]) and method type parameters (think def foo[T](t:
T)). They are nested, meaning that their return type can also be a
`PolyType` or a `MethodType`. To handle them, we traverse the symbols in
their definition -- for method types we traverse the types of the
parameters, while for poly types we add directly the dependency on the
symbol --so that the name of the type parameters are also recorded-- and
then we continue checking for their information if they are not a class,
that is, if they are an abstract type with a definition that we may need
to traverse (existential type, refined type, bounds, etc).

In the case of `TypeBounds`, we traverse them if they are not the
default specified by the SLS (`Nothing` for low bound, `Any` for high).

Refined types need special handling since we need to check their
declarations, that can introduce new type members or vals. If they do
have them, we add a dependency right away on those definitions.

As usual, `ThisType` and `ConstantType` need to be inspected by checking
their underlying representation (`C` in `C.this` and `12` in `Int(12)`).

`ExistentialType`, the last type on the traverser before falling back to
`mapOver`, has a list of symbols called `quantified` that needs to be
traversed since they are the symbol information that constrain the
existential type. As in the case of `TypeBounds`, we guard against the
default types `Nothing` for low bound and `Any` for high bound, so that
unnecessary names that are always present in source files don't appear.

This change triggers a very weird behaviour in 2.10, in which for some
reason the names `Nothing` and `Any` appear. This does not seem to come
from the new TypeDependencyTraverser and I've been able to track its
appearance to the case in the traverser where we check for `hasSymbol`
and add with `addSymbol`. I've added a TODO, which is not urgent, to
find out what's happening, since this only affect one concrete snippet
of the whole test code.

Benchmark:

```
[info] # Run complete. Total time: 00:25:51
[info]
[info] Benchmark                                                            (_tempDir)    Mode  Cnt           Score            Error   Units
[info] HotScalacBenchmark.compile                                    /tmp/sbt_abdb5ed2  sample   18       20893.226 ±        625.622   ms/op
[info] HotScalacBenchmark.compile:compile·p0.00                      /tmp/sbt_abdb5ed2  sample            19797.115                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.50                      /tmp/sbt_abdb5ed2  sample            21005.074                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.90                      /tmp/sbt_abdb5ed2  sample            21894.267                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.95                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.99                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.999                     /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.9999                    /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p1.00                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:·gc.alloc.rate                     /tmp/sbt_abdb5ed2  sample   18         289.838 ±          8.669  MB/sec
[info] HotScalacBenchmark.compile:·gc.alloc.rate.norm                /tmp/sbt_abdb5ed2  sample   18  6500730176.000 ±   13633760.029    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space            /tmp/sbt_abdb5ed2  sample   18         289.082 ±         24.260  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm       /tmp/sbt_abdb5ed2  sample   18  6480403569.778 ±  464987965.594    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen               /tmp/sbt_abdb5ed2  sample   18          12.679 ±         12.697  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm          /tmp/sbt_abdb5ed2  sample   18   290767194.667 ±  290528363.065    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space        /tmp/sbt_abdb5ed2  sample   18           7.321 ±          2.865  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm   /tmp/sbt_abdb5ed2  sample   18   165547052.444 ±   66661097.019    B/op
[info] HotScalacBenchmark.compile:·gc.count                          /tmp/sbt_abdb5ed2  sample   18         101.000                   counts
[info] HotScalacBenchmark.compile:·gc.time                           /tmp/sbt_abdb5ed2  sample   18       21332.000                       ms
[info] WarmScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2  sample    3       52769.937 ±       6743.004   ms/op
[info] WarmScalacBenchmark.compile:compile·p0.00                     /tmp/sbt_abdb5ed2  sample            52412.023                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.50                     /tmp/sbt_abdb5ed2  sample            52747.567                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.90                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.95                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.99                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.999                    /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.9999                   /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p1.00                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2  sample    3         125.382 ±         13.840  MB/sec
[info] WarmScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2  sample    3  7055970890.667 ± 1078954896.900    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2  sample    3         117.215 ±         73.864  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2  sample    3  6596470733.333 ± 4281843293.325    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2  sample    3           2.279 ±          1.015  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2  sample    3   128269752.000 ±   72721263.065    B/op
[info] WarmScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2  sample    3          73.000                   counts
[info] WarmScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2  sample    3        8746.000                       ms
[info] ColdScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2      ss   10       44611.286 ±        963.131   ms/op
[info] ColdScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2      ss   10         152.054 ±          2.753  MB/sec
[info] ColdScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2      ss   10  7249761568.800 ±   95126804.264    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2      ss   10         144.481 ±          9.964  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2      ss   10  6889406191.200 ±  490961958.245    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen              /tmp/sbt_abdb5ed2      ss   10          ≈ 10⁻³                   MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm         /tmp/sbt_abdb5ed2      ss   10       21136.000 ±     101049.368    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2      ss   10           2.848 ±          0.335  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2      ss   10   135792956.800 ±   16291050.509    B/op
[info] ColdScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2      ss   10         248.000                   counts
[info] ColdScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2      ss   10       29901.000                       ms
[success] Total time: 1553 s, completed Feb 26, 2017 3:06:29 AM
[success] Total time: 0 s, completed Feb 26, 2017 3:06:29 AM
```

jvican added a commit to scalacenter/zinc that referenced this issue Feb 26, 2017

Fix sbt#174: Register names for types and symbols
The following commit fixes the issues with as seen from that are
explained in this fantastic issue by Greg: sbt#174.

These issues are related to the fact that our previous approach was only
inspecting types, when some type information like type bounds is only
present in symbols. To get that information, we need a more precise
search that looks into the core of the Scalac types for the required
information.

Of course, type bounds is not all we're interested about. The issue is
that type members, method parameters and type parameters can have type
information in its definition that is necessary at the use site to
detect and propagate changes. This information is also tied to the fact
that type members can have different materializations depending on the
prefix (both because of type members and path-dependent types).

`types-in-used-names-b` and `as-seen-from-b` are a perfect example of
this. This commit turns them into passing tests.

Having more in-depth look at the algorithm behind it will help us
understand what it does. In essence, the new type traverser is the
responsible of adding dependencies on every `TypeRef` and `SingleType`.
They contain concrete information about types (they are materialized),
so their presence must be recorded.

We also have the presence of other types like `PolyType` and
`MethodType`. These types are used for defining type parameters for
classes (think List[A]) and method type parameters (think def foo[T](t:
T)). They are nested, meaning that their return type can also be a
`PolyType` or a `MethodType`. To handle them, we traverse the symbols in
their definition -- for method types we traverse the types of the
parameters, while for poly types we add directly the dependency on the
symbol --so that the name of the type parameters are also recorded-- and
then we continue checking for their information if they are not a class,
that is, if they are an abstract type with a definition that we may need
to traverse (existential type, refined type, bounds, etc).

In the case of `TypeBounds`, we traverse them if they are not the
default specified by the SLS (`Nothing` for low bound, `Any` for high).

Refined types need special handling since we need to check their
declarations, that can introduce new type members or vals. If they do
have them, we add a dependency right away on those definitions.

As usual, `ThisType` and `ConstantType` need to be inspected by checking
their underlying representation (`C` in `C.this` and `12` in `Int(12)`).

`ExistentialType`, the last type on the traverser before falling back to
`mapOver`, has a list of symbols called `quantified` that needs to be
traversed since they are the symbol information that constrain the
existential type. As in the case of `TypeBounds`, we guard against the
default types `Nothing` for low bound and `Any` for high bound, so that
unnecessary names that are always present in source files don't appear.

This change triggers a very weird behaviour in 2.10, in which for some
reason the names `Nothing` and `Any` appear. This does not seem to come
from the new TypeDependencyTraverser and I've been able to track its
appearance to the case in the traverser where we check for `hasSymbol`
and add with `addSymbol`. I've added a TODO, which is not urgent, to
find out what's happening, since this only affect one concrete snippet
of the whole test code.

Benchmark:

```
[info] # Run complete. Total time: 00:25:51
[info]
[info] Benchmark                                                            (_tempDir)    Mode  Cnt           Score            Error   Units
[info] HotScalacBenchmark.compile                                    /tmp/sbt_abdb5ed2  sample   18       20893.226 ±        625.622   ms/op
[info] HotScalacBenchmark.compile:compile·p0.00                      /tmp/sbt_abdb5ed2  sample            19797.115                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.50                      /tmp/sbt_abdb5ed2  sample            21005.074                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.90                      /tmp/sbt_abdb5ed2  sample            21894.267                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.95                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.99                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.999                     /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.9999                    /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p1.00                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:·gc.alloc.rate                     /tmp/sbt_abdb5ed2  sample   18         289.838 ±          8.669  MB/sec
[info] HotScalacBenchmark.compile:·gc.alloc.rate.norm                /tmp/sbt_abdb5ed2  sample   18  6500730176.000 ±   13633760.029    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space            /tmp/sbt_abdb5ed2  sample   18         289.082 ±         24.260  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm       /tmp/sbt_abdb5ed2  sample   18  6480403569.778 ±  464987965.594    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen               /tmp/sbt_abdb5ed2  sample   18          12.679 ±         12.697  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm          /tmp/sbt_abdb5ed2  sample   18   290767194.667 ±  290528363.065    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space        /tmp/sbt_abdb5ed2  sample   18           7.321 ±          2.865  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm   /tmp/sbt_abdb5ed2  sample   18   165547052.444 ±   66661097.019    B/op
[info] HotScalacBenchmark.compile:·gc.count                          /tmp/sbt_abdb5ed2  sample   18         101.000                   counts
[info] HotScalacBenchmark.compile:·gc.time                           /tmp/sbt_abdb5ed2  sample   18       21332.000                       ms
[info] WarmScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2  sample    3       52769.937 ±       6743.004   ms/op
[info] WarmScalacBenchmark.compile:compile·p0.00                     /tmp/sbt_abdb5ed2  sample            52412.023                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.50                     /tmp/sbt_abdb5ed2  sample            52747.567                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.90                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.95                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.99                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.999                    /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.9999                   /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p1.00                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2  sample    3         125.382 ±         13.840  MB/sec
[info] WarmScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2  sample    3  7055970890.667 ± 1078954896.900    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2  sample    3         117.215 ±         73.864  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2  sample    3  6596470733.333 ± 4281843293.325    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2  sample    3           2.279 ±          1.015  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2  sample    3   128269752.000 ±   72721263.065    B/op
[info] WarmScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2  sample    3          73.000                   counts
[info] WarmScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2  sample    3        8746.000                       ms
[info] ColdScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2      ss   10       44611.286 ±        963.131   ms/op
[info] ColdScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2      ss   10         152.054 ±          2.753  MB/sec
[info] ColdScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2      ss   10  7249761568.800 ±   95126804.264    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2      ss   10         144.481 ±          9.964  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2      ss   10  6889406191.200 ±  490961958.245    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen              /tmp/sbt_abdb5ed2      ss   10          ≈ 10⁻³                   MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm         /tmp/sbt_abdb5ed2      ss   10       21136.000 ±     101049.368    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2      ss   10           2.848 ±          0.335  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2      ss   10   135792956.800 ±   16291050.509    B/op
[info] ColdScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2      ss   10         248.000                   counts
[info] ColdScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2      ss   10       29901.000                       ms
[success] Total time: 1553 s, completed Feb 26, 2017 3:06:29 AM
[success] Total time: 0 s, completed Feb 26, 2017 3:06:29 AM
```

jvican added a commit to scalacenter/zinc that referenced this issue Feb 26, 2017

Fix sbt#174: Register names for types and symbols
The following commit fixes the issues with as seen from that are
explained in this fantastic issue by Greg: sbt#174, as well as sbt#239 that
handles structural types.

These issues are related to the fact that our previous approach was only
inspecting types, when some type information like type bounds is only
present in symbols. To get that information, we need a more precise
search that looks into the core of the Scalac types for the required
information.

Of course, type bounds is not all we're interested about. The issue is
that type members, method parameters and type parameters can have type
information in its definition that is necessary at the use site to
detect and propagate changes. This information is also tied to the fact
that type members can have different materializations depending on the
prefix (both because of type members and path-dependent types).

`types-in-used-names-b` and `as-seen-from-b` are a perfect example of
this. This commit turns them into passing tests.

Having more in-depth look at the algorithm behind it will help us
understand what it does. In essence, the new type traverser is the
responsible of adding dependencies on every `TypeRef` and `SingleType`.
They contain concrete information about types (they are materialized),
so their presence must be recorded.

We also have the presence of other types like `PolyType` and
`MethodType`. These types are used for defining type parameters for
classes (think List[A]) and method type parameters (think def foo[T](t:
T)). They are nested, meaning that their return type can also be a
`PolyType` or a `MethodType`. To handle them, we traverse the symbols in
their definition -- for method types we traverse the types of the
parameters, while for poly types we add directly the dependency on the
symbol --so that the name of the type parameters are also recorded-- and
then we continue checking for their information if they are not a class,
that is, if they are an abstract type with a definition that we may need
to traverse (existential type, refined type, bounds, etc).

In the case of `TypeBounds`, we traverse them if they are not the
default specified by the SLS (`Nothing` for low bound, `Any` for high).

Refined types need special handling since we need to check their
declarations, that can introduce new type members or vals. If they do
have them, we add a dependency right away on those definitions.

As usual, `ThisType` and `ConstantType` need to be inspected by checking
their underlying representation (`C` in `C.this` and `12` in `Int(12)`).

`ExistentialType`, the last type on the traverser before falling back to
`mapOver`, has a list of symbols called `quantified` that needs to be
traversed since they are the symbol information that constrain the
existential type. As in the case of `TypeBounds`, we guard against the
default types `Nothing` for low bound and `Any` for high bound, so that
unnecessary names that are always present in source files don't appear.

This change triggers a very weird behaviour in 2.10, in which for some
reason the names `Nothing` and `Any` appear. This does not seem to come
from the new TypeDependencyTraverser and I've been able to track its
appearance to the case in the traverser where we check for `hasSymbol`
and add with `addSymbol`. I've added a TODO, which is not urgent, to
find out what's happening, since this only affect one concrete snippet
of the whole test code.

Benchmark:

```
[info] # Run complete. Total time: 00:25:51
[info]
[info] Benchmark                                                            (_tempDir)    Mode  Cnt           Score            Error   Units
[info] HotScalacBenchmark.compile                                    /tmp/sbt_abdb5ed2  sample   18       20893.226 ±        625.622   ms/op
[info] HotScalacBenchmark.compile:compile·p0.00                      /tmp/sbt_abdb5ed2  sample            19797.115                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.50                      /tmp/sbt_abdb5ed2  sample            21005.074                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.90                      /tmp/sbt_abdb5ed2  sample            21894.267                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.95                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.99                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.999                     /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.9999                    /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p1.00                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:·gc.alloc.rate                     /tmp/sbt_abdb5ed2  sample   18         289.838 ±          8.669  MB/sec
[info] HotScalacBenchmark.compile:·gc.alloc.rate.norm                /tmp/sbt_abdb5ed2  sample   18  6500730176.000 ±   13633760.029    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space            /tmp/sbt_abdb5ed2  sample   18         289.082 ±         24.260  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm       /tmp/sbt_abdb5ed2  sample   18  6480403569.778 ±  464987965.594    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen               /tmp/sbt_abdb5ed2  sample   18          12.679 ±         12.697  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm          /tmp/sbt_abdb5ed2  sample   18   290767194.667 ±  290528363.065    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space        /tmp/sbt_abdb5ed2  sample   18           7.321 ±          2.865  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm   /tmp/sbt_abdb5ed2  sample   18   165547052.444 ±   66661097.019    B/op
[info] HotScalacBenchmark.compile:·gc.count                          /tmp/sbt_abdb5ed2  sample   18         101.000                   counts
[info] HotScalacBenchmark.compile:·gc.time                           /tmp/sbt_abdb5ed2  sample   18       21332.000                       ms
[info] WarmScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2  sample    3       52769.937 ±       6743.004   ms/op
[info] WarmScalacBenchmark.compile:compile·p0.00                     /tmp/sbt_abdb5ed2  sample            52412.023                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.50                     /tmp/sbt_abdb5ed2  sample            52747.567                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.90                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.95                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.99                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.999                    /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.9999                   /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p1.00                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2  sample    3         125.382 ±         13.840  MB/sec
[info] WarmScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2  sample    3  7055970890.667 ± 1078954896.900    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2  sample    3         117.215 ±         73.864  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2  sample    3  6596470733.333 ± 4281843293.325    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2  sample    3           2.279 ±          1.015  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2  sample    3   128269752.000 ±   72721263.065    B/op
[info] WarmScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2  sample    3          73.000                   counts
[info] WarmScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2  sample    3        8746.000                       ms
[info] ColdScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2      ss   10       44611.286 ±        963.131   ms/op
[info] ColdScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2      ss   10         152.054 ±          2.753  MB/sec
[info] ColdScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2      ss   10  7249761568.800 ±   95126804.264    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2      ss   10         144.481 ±          9.964  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2      ss   10  6889406191.200 ±  490961958.245    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen              /tmp/sbt_abdb5ed2      ss   10          ≈ 10⁻³                   MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm         /tmp/sbt_abdb5ed2      ss   10       21136.000 ±     101049.368    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2      ss   10           2.848 ±          0.335  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2      ss   10   135792956.800 ±   16291050.509    B/op
[info] ColdScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2      ss   10         248.000                   counts
[info] ColdScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2      ss   10       29901.000                       ms
[success] Total time: 1553 s, completed Feb 26, 2017 3:06:29 AM
[success] Total time: 0 s, completed Feb 26, 2017 3:06:29 AM
```

jvican added a commit to scalacenter/zinc that referenced this issue Feb 26, 2017

Fix sbt#174: Register names for types and symbols
The following commit fixes the issues with as seen from that are
explained in this fantastic issue by Greg: sbt#174, as well as sbt#239 that
handles structural types.

These issues are related to the fact that our previous approach was only
inspecting types, when some type information like type bounds is only
present in symbols. To get that information, we need a more precise
search that looks into the core of the Scalac types for the required
information.

Of course, type bounds is not all we're interested about. The issue is
that type members, method parameters and type parameters can have type
information in its definition that is necessary at the use site to
detect and propagate changes. This information is also tied to the fact
that type members can have different materializations depending on the
prefix (both because of type members and path-dependent types).

`types-in-used-names-b` and `as-seen-from-b` are a perfect example of
this. This commit turns them into passing tests.

Having more in-depth look at the algorithm behind it will help us
understand what it does. In essence, the new type traverser is the
responsible of adding dependencies on every `TypeRef` and `SingleType`.
They contain concrete information about types (they are materialized),
so their presence must be recorded.

We also have the presence of other types like `PolyType` and
`MethodType`. These types are used for defining type parameters for
classes (think List[A]) and method type parameters (think def foo[T](t:
T)). They are nested, meaning that their return type can also be a
`PolyType` or a `MethodType`. To handle them, we traverse the symbols in
their definition -- for method types we traverse the types of the
parameters, while for poly types we add directly the dependency on the
symbol --so that the name of the type parameters are also recorded-- and
then we continue checking for their information if they are not a class,
that is, if they are an abstract type with a definition that we may need
to traverse (existential type, refined type, bounds, etc).

In the case of `TypeBounds`, we traverse them if they are not the
default specified by the SLS (`Nothing` for low bound, `Any` for high).

Refined types need special handling since we need to check their
declarations, that can introduce new type members or vals. If they do
have them, we add a dependency right away on those definitions.

As usual, `ThisType` and `ConstantType` need to be inspected by checking
their underlying representation (`C` in `C.this` and `12` in `Int(12)`).

`ExistentialType`, the last type on the traverser before falling back to
`mapOver`, has a list of symbols called `quantified` that needs to be
traversed since they are the symbol information that constrain the
existential type. As in the case of `TypeBounds`, we guard against the
default types `Nothing` for low bound and `Any` for high bound, so that
unnecessary names that are always present in source files don't appear.

This change triggers a very weird behaviour in 2.10, in which for some
reason the names `Nothing` and `Any` appear. This does not seem to come
from the new TypeDependencyTraverser and I've been able to track its
appearance to the case in the traverser where we check for `hasSymbol`
and add with `addSymbol`. I've added a TODO, which is not urgent, to
find out what's happening, since this only affect one concrete snippet
of the whole test code.

Benchmark:

```
[info] # Run complete. Total time: 00:25:51
[info]
[info] Benchmark                                                            (_tempDir)    Mode  Cnt           Score            Error   Units
[info] HotScalacBenchmark.compile                                    /tmp/sbt_abdb5ed2  sample   18       20893.226 ±        625.622   ms/op
[info] HotScalacBenchmark.compile:compile·p0.00                      /tmp/sbt_abdb5ed2  sample            19797.115                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.50                      /tmp/sbt_abdb5ed2  sample            21005.074                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.90                      /tmp/sbt_abdb5ed2  sample            21894.267                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.95                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.99                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.999                     /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p0.9999                    /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:compile·p1.00                      /tmp/sbt_abdb5ed2  sample            22045.262                    ms/op
[info] HotScalacBenchmark.compile:·gc.alloc.rate                     /tmp/sbt_abdb5ed2  sample   18         289.838 ±          8.669  MB/sec
[info] HotScalacBenchmark.compile:·gc.alloc.rate.norm                /tmp/sbt_abdb5ed2  sample   18  6500730176.000 ±   13633760.029    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space            /tmp/sbt_abdb5ed2  sample   18         289.082 ±         24.260  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm       /tmp/sbt_abdb5ed2  sample   18  6480403569.778 ±  464987965.594    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen               /tmp/sbt_abdb5ed2  sample   18          12.679 ±         12.697  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm          /tmp/sbt_abdb5ed2  sample   18   290767194.667 ±  290528363.065    B/op
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space        /tmp/sbt_abdb5ed2  sample   18           7.321 ±          2.865  MB/sec
[info] HotScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm   /tmp/sbt_abdb5ed2  sample   18   165547052.444 ±   66661097.019    B/op
[info] HotScalacBenchmark.compile:·gc.count                          /tmp/sbt_abdb5ed2  sample   18         101.000                   counts
[info] HotScalacBenchmark.compile:·gc.time                           /tmp/sbt_abdb5ed2  sample   18       21332.000                       ms
[info] WarmScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2  sample    3       52769.937 ±       6743.004   ms/op
[info] WarmScalacBenchmark.compile:compile·p0.00                     /tmp/sbt_abdb5ed2  sample            52412.023                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.50                     /tmp/sbt_abdb5ed2  sample            52747.567                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.90                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.95                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.99                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.999                    /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p0.9999                   /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:compile·p1.00                     /tmp/sbt_abdb5ed2  sample            53150.220                    ms/op
[info] WarmScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2  sample    3         125.382 ±         13.840  MB/sec
[info] WarmScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2  sample    3  7055970890.667 ± 1078954896.900    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2  sample    3         117.215 ±         73.864  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2  sample    3  6596470733.333 ± 4281843293.325    B/op
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2  sample    3           2.279 ±          1.015  MB/sec
[info] WarmScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2  sample    3   128269752.000 ±   72721263.065    B/op
[info] WarmScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2  sample    3          73.000                   counts
[info] WarmScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2  sample    3        8746.000                       ms
[info] ColdScalacBenchmark.compile                                   /tmp/sbt_abdb5ed2      ss   10       44611.286 ±        963.131   ms/op
[info] ColdScalacBenchmark.compile:·gc.alloc.rate                    /tmp/sbt_abdb5ed2      ss   10         152.054 ±          2.753  MB/sec
[info] ColdScalacBenchmark.compile:·gc.alloc.rate.norm               /tmp/sbt_abdb5ed2      ss   10  7249761568.800 ±   95126804.264    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space           /tmp/sbt_abdb5ed2      ss   10         144.481 ±          9.964  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Eden_Space.norm      /tmp/sbt_abdb5ed2      ss   10  6889406191.200 ±  490961958.245    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen              /tmp/sbt_abdb5ed2      ss   10          ≈ 10⁻³                   MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Old_Gen.norm         /tmp/sbt_abdb5ed2      ss   10       21136.000 ±     101049.368    B/op
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space       /tmp/sbt_abdb5ed2      ss   10           2.848 ±          0.335  MB/sec
[info] ColdScalacBenchmark.compile:·gc.churn.PS_Survivor_Space.norm  /tmp/sbt_abdb5ed2      ss   10   135792956.800 ±   16291050.509    B/op
[info] ColdScalacBenchmark.compile:·gc.count                         /tmp/sbt_abdb5ed2      ss   10         248.000                   counts
[info] ColdScalacBenchmark.compile:·gc.time                          /tmp/sbt_abdb5ed2      ss   10       29901.000                       ms
[success] Total time: 1553 s, completed Feb 26, 2017 3:06:29 AM
[success] Total time: 0 s, completed Feb 26, 2017 3:06:29 AM
```

eed3si9n added a commit that referenced this issue Feb 27, 2017

Merge pull request #239 from jvican/as-seen-from
Fix #174 and #240: Register names for types and symbols

@eed3si9n eed3si9n removed the in progress label Feb 27, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment