Files
kotlin-fork/compiler/testData/diagnostics/tests/cyclicHierarchy/withCompanion/withMembers.kt
T
Dmitry Savvinov 874267b79d Report cyclic scopes properly
This commit introduces proper handling of recursion in scopes, which
could occur when some of companion object supertypes are members of
that companion owner:

```
class Container {
  open class Base
  companion object : Base()
}
```

To resolve `Base`, we have to build member scope for `Container`.
In the member scope of `Container`, we see all classifiers from
companion and his supertypes
So, we have to resolve companion objects supertype, which happens to be
`Base` again - therefore, we encounter recursion here.

Previously, we created `ThrowingLexicalScope` for such recursive calls,
but didn't checked for loop explicitly, which lead to a wide variety of
bugs (see https://jetbrains.quip.com/dc5aABhZoaQY and KT-10532).

To report such cyclic declarations properly, we first change
`ThrowingLexicalScope` to `ErrorLexicalScope` -- the main difference is
that latter doesn't throws ISE when someone tries to resolve type in it,
allowing us to report error instead of crashing with exception.

Then, we add additional fake edge in supertypes graph (from
host-class to companion object) which allows us to piggyback on existing
supertypes loops detection mechanism, and report such cycles for user.
2017-12-07 14:14:08 +03:00

63 lines
1.9 KiB
Kotlin
Vendored

// see https://youtrack.jetbrains.com/issue/KT-21515
object WithFunctionInBase {
abstract class <!CYCLIC_SCOPES_WITH_COMPANION!>DerivedAbstract<!> : C.Base()
class Data
public class C {
// error-scope
val data: <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>Data<!> = Data()
open class <!CYCLIC_SCOPES_WITH_COMPANION!>Base<!>() {
// error-scope
fun foo(): <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>Int<!> = 42
}
companion <!CYCLIC_SCOPES_WITH_COMPANION!>object<!> : DerivedAbstract()
}
}
object WithPropertyInBase {
// This case is very similar to previous one, but there are subtle differences from POV of implementation
abstract class <!CYCLIC_SCOPES_WITH_COMPANION!>DerivedAbstract<!> : C.Base()
class Data
public class C {
open class <!CYCLIC_SCOPES_WITH_COMPANION!>Base<!>() {
// error-scope
val foo: <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>Int<!> = 42
}
// error-scope
val data: <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>Data<!> = Data()
companion <!CYCLIC_SCOPES_WITH_COMPANION!>object<!> : DerivedAbstract()
}
}
object WithPropertyInBaseDifferentOrder {
// This case is very similar to previous one, but there are subtle differences from POV of implementation
// Note how position of property in file affected order of resolve, and, consequently, its results and
// diagnostics.
abstract class <!CYCLIC_SCOPES_WITH_COMPANION!>DerivedAbstract<!> : C.Base()
class Data
public class C {
// Now it is succesfully resolved (vs. ErrorType like in the previous case)
val data: Data = Data()
open class <!CYCLIC_SCOPES_WITH_COMPANION!>Base<!>() {
// Now it is unresolved (vs. ErrorType like in the previous case)
val foo: <!UNRESOLVED_REFERENCE!>Int<!> = 42
}
companion <!CYCLIC_SCOPES_WITH_COMPANION!>object<!> : DerivedAbstract()
}
}