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
[SR-4358] Generic trouble #46937
Comments
Comment by Dmitriy (JIRA) Hello, @slavapestov! |
My understanding is that we don't support cycles in the runtime metadata yet. cc @rjmccall |
That's correct. |
Comment by Dmitriy (JIRA) It seems that there is the cycles too, but it work: protocol P1 {
associatedtype Type1
associatedtype Type2
var value1: Type1? { get set }
var value2: Type2? { get set }
}
protocol P2: P1 { }
class C1: P1 {
typealias Type1 = C1
typealias Type2 = C2
var value1: C1?
var value2: C2?
}
class C2: C1, P2 {} But this is not that I need, because there is no division into layers:
|
Can you do the layering without subclassing, or at least without naming the subclass as a generic argument for the superclass? ("But this is not what I need" was correct, by the way.) |
Comment by Dmitriy (JIRA) Simple sample - a doubly linked list whose first and other(next) elements differ No generic: // Framework layer
protocol PListNode {
var next: POtherListNode? { get }
func setNext(node: POtherListNode)
func getFirstNode() -> PFirstListNode
}
protocol PFirstListNode: PListNode {
}
protocol POtherListNode: PListNode {
var previous: PListNode { get }
}
class AbstractListNode: PListNode {
var next: POtherListNode?
func setNext(node: POtherListNode) {
//implementation
}
func getFirstNode() -> PFirstListNode {
//implementation
}
}
class FirstListNode: AbstractListNode, PFirstListNode {
}
class OtherListNode: AbstractListNode, POtherListNode {
var previous: PListNode
init(previous: AbstractListNode) {
self.previous = previous
}
}
// User layer
protocol PCustomListNode: PListNode {
var value1: String? { get }
}
protocol PCustomFirstListNode: PCustomListNode, PFirstListNode {
var value2: String? { get }
}
protocol PCustomOtherListNode: PCustomListNode, POtherListNode {
var value3: String? { get }
}
class CustomListNode: AbstractListNode, PCustomListNode {
var value1: String?
}
class CustomFirstListNode: FirstListNode, PCustomFirstListNode {
var value1: String?
var value2: String?
}
class CustomOtherListNode: OtherListNode, PCustomOtherListNode {
var value1: String?
var value3: String?
}
// Using
let firstNode = someNode.getFirstNode() as! CustomFirstListNode // type downcasting Generic: // Framework layer
protocol PListNode {
associatedtype ListNodeType
associatedtype FirstListNodeType
associatedtype OtherListNodeType
var next: OtherListNodeType? { get }
func setNext(node: OtherListNodeType)
func getFirst() -> FirstListNodeType
}
protocol PFirstListNode: PListNode {
}
protocol POtherListNode: PListNode {
var previous: ListNodeType { get }
}
class BaseListNode<ListNodeT, FirstListNodeT, OtherListNodeT>: PListNode {
typealias ListNodeType = ListNodeT
typealias FirstListNodeType = FirstListNodeT
typealias OtherListNodeType = OtherListNodeT
var next: OtherListNodeT?
func setNext(node: OtherListNodeT) {
//implementation
}
func getFirst() -> FirstListNodeT {
//implementation
}
}
class BaseFirstListNode<ListNodeT, FirstListNodeT, OtherListNodeT>: BaseListNode<ListNodeT, FirstListNodeT, OtherListNodeT> {
}
class BaseOtherListNode<ListNodeT, FirstListNodeT, OtherListNodeT>: BaseListNode<ListNodeT, FirstListNodeT, OtherListNodeT> {
var previous: ListNodeT
}
// User layer
protocol PCustomListNode {
var value1: String? { get }
}
protocol PCustomFirstListNode: PCustomListNode {
var value2: String? { get }
}
protocol PCustomOtherListNode: PCustomListNode {
var value3: String? { get }
}
class CustomListNode: BaseListNode<CustomListNode, CustomFirstListNode, CustomOtherListNode>, PCustomListNode {
var value1: String?
}
class CustomFirstListNode: BaseFirstListNode<CustomListNode, CustomFirstListNode, CustomOtherListNode>, PCustomFirstListNode {
var value1: String?
var value2: String?
}
class CustomFirstListNode: BaseOtherListNode<CustomListNode, CustomFirstListNode, CustomOtherListNode>, PCustomOtherListNode {
var value1: String?
var value3: String?
}
// Using
let firstNode = someNode.getFirst() // no type downcasting |
Do you really need the list node to be generic over its subclass vs. just making it carry some arbitrary payload type, though? final class ListNode<T> {
private var previous: ListNode<T>?
private var next: ListNode<T>?
var value: T
init(value: T) {
self.value = value
}
} |
Granted, your code should work; I'm just trying to suggest alternative designs that won't have this cyclic-metadata problem. |
Comment by Dmitriy (JIRA) John, thanks for your help. Explanation: ListNode name is bad. I want not to make generic collection data object. ListNode, FirstListNode, OtherListNode is business or presentation layer objects. Their relationship «first-other» is primary characteristic (in my case). Inheritance(subclassing) is justified, imho. First and other object is absolutely different object. For example:
By the way, I forgot one more method: protocol PFirstListNode: PListNode {
func setPrevious(node: ListNodeType) // polymorphism, don't need to know the specific type: first or other
} So, is the trouble described in the topic an bug or feature or something else? Is it possible to expect that this will be corrected in Swift version 3.1, 4 … 9? 🙂 |
I understand that you're trying to write a very generic operation here, but it's actually quite invasive upon your clients to demand that they subclass ListNode, because it means they can't subclass anything else. Anyway, I'm not trying to design your library, just point out things you could do that would still work with the current limitations. It is unlikely that we will fix this in Swift 4. |
Comment by Dmitriy (JIRA) Thanks. I'll think what to do |
Environment
Swift 4.0 Snapshot 2017-06-02 (a)
Additional Detail from JIRA
md5: c7d122f15460e95717423d4364c93f2d
duplicates:
Issue Description:
Hello!
Generics:
Using:
No compile errors. No runtime errors. But "end" never printed.
The text was updated successfully, but these errors were encountered: