mirror of https://github.com/sbt/sbt.git
Only include all base types for class definitions
For refinement types, the Structure was already restricted
to declarations (and not inherited members), but all base types
were still included for a refinement's parents, which would
create unwieldy, and even erroneous (cyclic) types by expanding
all constituents of an intersection type to add all base types.
Since the logic already disregarded inherited members, it seems
logical to only include direct parents, and not all ancestor types.
```
class Dep {
def bla(c: Boolean) = if (c) new Value else "bla"
}
class Value extends java.lang.Comparable[Value] { def compareTo(that: Value): Int = 1 }
```
This commit is contained in:
parent
3e03e0d1b5
commit
9346e2bb4d
|
|
@ -336,14 +336,19 @@ class ExtractAPI[GlobalType <: CallbackGlobal](val global: GlobalType,
|
|||
|
||||
private def removeConstructors(ds: List[Symbol]): List[Symbol] = ds filter { !_.isConstructor }
|
||||
|
||||
private def mkStructure(info: Type, s: Symbol, inherit: Boolean): xsbti.api.Structure =
|
||||
{
|
||||
val (declared, inherited) = info.members.toList.reverse.partition(_.owner == s)
|
||||
val baseTypes = info.baseClasses.tail.map(info.baseType)
|
||||
val ds = if (s.isModuleClass) removeConstructors(declared) else declared
|
||||
val is = if (inherit) removeConstructors(inherited) else Nil
|
||||
mkStructure(s, baseTypes, ds, is)
|
||||
}
|
||||
private def mkStructure(info: Type, s: Symbol, inherit: Boolean): xsbti.api.Structure = {
|
||||
val (declared, inherited) = info.members.reverse.partition(_.owner == s)
|
||||
// Note that the ordering of classes in `baseClasses` is important.
|
||||
// It would be easier to just say `val baseTypes = baseTypeSeq`, but that does not seem
|
||||
// to take linearization into account.
|
||||
// Also, we take info.parents when we're not interested in the full linearization,
|
||||
// which side steps issues with baseType when f-bounded existential types and refined types mix
|
||||
// (and we get cyclic types which cause a stack overflow in showAPI)
|
||||
val baseTypes = if (inherit) info.baseClasses.tail.map(info.baseType) else info.parents
|
||||
val ds = if (s.isModuleClass) removeConstructors(declared) else declared
|
||||
val is = if (inherit) removeConstructors(inherited) else Nil
|
||||
mkStructure(s, baseTypes, ds, is)
|
||||
}
|
||||
|
||||
// If true, this template is publicly visible and should be processed as a public inheritance dependency.
|
||||
// Local classes and local refinements will never be traversed by the api phase, so we don't need to check for that.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
class Dep {
|
||||
// The API representation for `bla`'s result type contains a cycle
|
||||
// (an existential's type variable's bound is the existential type itself)
|
||||
// This results in a stack overflow while showing the API diff.
|
||||
// Note that the actual result type in the compiler is not cyclic
|
||||
// (the f-bounded existential for Comparable is truncated)
|
||||
def bla(c: Boolean) = if (c) new Value else "bla"
|
||||
}
|
||||
|
||||
class Value extends java.lang.Comparable[Value] { def compareTo(that: Value): Int = 1 }
|
||||
|
|
@ -0,0 +1 @@
|
|||
> compile
|
||||
Loading…
Reference in New Issue