Consider signatures of methods before and after erasure in ExtractAPI#2261
Consider signatures of methods before and after erasure in ExtractAPI#2261
Conversation
The signatures of methods that have value classes as arguments or return type change during the erasure phase. Because we only registered signatures before the erasure, we missed some API changes when a class was changed to a value class (or a value class changed to a class). This commit fixes this problem by recording the signatures of method before and after erasure. Fixes sbt#1171
|
Can one of the admins verify this patch? |
|
@Duhemm Could you fix the codacy failure due to the lack of return type signature on public method, plz? |
Consider signatures of methods before and after erasure in ExtractAPI
|
Very cool. Nice to see old, old bugs get fixes. Well done. |
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 }
```
|
This needs to be forward ported. |
|
//cc @Duhemm |
|
@gkossakowski I didn't. I think that the increase of the size of the API has been somewhat mitigated by #2414. I'll try to look into it. |
|
Oh, I didn't see #2414. It will indeed help with API structure size. Do you need to detect whether a type in a signature just changed from a value class to a regular class or do you need the full information about what it erases to? |
|
It's still bigger than it needs to be, consider: class A(val self: Int) extends AnyVal
class B {
def foo(a: A): A = new A(1)
}Then ExtractAPI returns four signatures for def foo(a: this#A): this#A
def foo(a: this#A): scala.this#Int
def foo(a: scala.this#Int): this#A
def foo(a: scala.this#Int): scala.this#Int |
|
Would it be enough to introduce a special |
|
I think you still need to know what the underlying type is, consider three files class A(val self: Int) extends AnyVal
object B {
def foo: A = new A(1)
}
object C {
def main(args: Array[String]): Unit = {
B.foo
}
}If we change the underlying type of |
|
Yes, you're right. However, the issue is that there're two different ways to refer to |
That seems like a nice idea, though instead of having a reference to the erased type, I'd like to have a reference to the underlying type. In Dotty, a value class can have another value class as its underlying type. |
The previous approach to value class API (introduced by sbt/sbt#2261 and refined by sbt/sbt#2413 and sbt/sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#87: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that use a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of <init> change and since every class uses the name <init>, we don't need to do anything special to trigger recompilations either.
The previous approach to value class API (introduced by sbt/sbt#2261 and refined by sbt/sbt#2413 and sbt/sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#87: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that use a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of <init> change and since every class uses the name <init>, we don't need to do anything special to trigger recompilations either.
The previous approach to value class API (introduced by sbt/sbt#2261 and refined by sbt/sbt#2413 and sbt/sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#87: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of <init> change and since every class uses the name <init>, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
This is a backport of sbt/zinc#95 The previous approach to value class API (introduced by sbt#2261 and refined by sbt#2413 and sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to sbt#2523: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of `<init>` changes and since every class uses the name `<init>`, we don't need to do anything special to trigger recompilations either.
The previous approach to value class API (introduced by sbt/sbt#2261 and refined by sbt/sbt#2413 and sbt/sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to scala#87: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of <init> change and since every class uses the name <init>, we don't need to do anything special to trigger recompilations either.
Rewritten from sbt/zinc@db84f4c
The previous approach to value class API (introduced by sbt/sbt#2261 and refined by sbt/sbt#2413 and sbt/sbt#2414) was to store both unerased and erased signatures so that changes to value classes forced recompilations. This is no longer necessary thanks to scala#87: if a class type is used, then it becomes a dependency of the current class and its name is part of the used names of the current class. Since the name hash of a class changes if it stops or start extending AnyVal, this is enough to force recompilation of anything that uses a value class type. If the underlying type of a value class change, its name hash doesn't change, but the name hash of <init> change and since every class uses the name <init>, we don't need to do anything special to trigger recompilations either. Rewritten from sbt/zinc@1e7e99e
The signatures of methods that have value classes as arguments or return
type change during the erasure phase. Because we only registered
signatures before the erasure, we missed some API changes when a class
was changed to a value class (or a value class changed to a class).
This commit fixes this problem by recording the signatures of method
before and after erasure.
Fixes #1171