Skip to content
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-5828] Cyclical metadata graphs should either not be formed or be a compile failure #48398

Closed
phausler opened this issue Sep 3, 2017 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@phausler
Copy link
Member

phausler commented Sep 3, 2017

Previous ID SR-5828
Radar None
Original Reporter @phausler
Type Bug
Status Resolved
Resolution Duplicate
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: b457abbc31a13836352c0eba2d4a2ccc

duplicates:

  • SR-263 Implement a general solution to prevent deadlocks when generic types rely on their own metadata recursively

relates to:

  • SR-263 Implement a general solution to prevent deadlocks when generic types rely on their own metadata recursively

Issue Description:

consider the following code:

enum _TrieNode<Element : Equatable> {
    case leaf(Array<Element>)
    case node(Element, Array<_TrieNode<Element>>)
    
    mutating func insert<I>(_ iterator: inout I) -> _TrieNode<Element>? where I : IteratorProtocol, I.Element == Element {
        if let element = iterator.next() {
            switch self {
            case .leaf(let elements):
                let filtered = elements.filter { $0 != element }
                var items = [Element]()
                while let item = iterator.next() {
                    items.append(item)
                }
                self = .node(element, [.leaf(items)])
                return .leaf(filtered)
            case .node(let nodeElement, let children_):
                var children = children_
                for idx in 0..<children.count {
                    if children[idx].matches(element) {
                        if let additional = children[idx].insert(&iterator) {
                            children.append(additional)
                        }
                        break
                    }
                }
                self = .node(nodeElement, children)
                return nil
            }
        }
        return nil
    }
    
    func matches(_ element: Element) -> Bool {
        switch self {
        case .leaf(let elements):
            return elements.contains(element)
        case .node(let nodeElement, _):
            return nodeElement == element
        }
    }
}

struct Trie<Element : Equatable> {
    var nodes = [_TrieNode<Element>]()
    
    mutating func insert<C>(_ elements: C) where C : Sequence, C.Iterator.Element == Element {
        var iter = elements.makeIterator()
        if let element = iter.next() {
            for idx in 0..<nodes.count {
                if nodes[idx].matches(element) {
                    if let additional = nodes[idx].insert(&iter) {
                        nodes.append(additional)
                    }
                    return
                }
            }
        }
    }
}

var trie = Trie<String.Element>()
trie.insert("hello")
trie.insert("hello world")

Since this code compiles I would expect it would execute with no failures. Unfortunately it seems to hit a runtime failure?

GenericCache(0x1005d54f8): cyclic metadata dependency detected, aborting

Either these types of metadata dependencies should not be created or it should be compile failure. Additionally this debugging information is not very actionable to help avoid this type of cyclical graph.

@belkadan
Copy link
Contributor

belkadan commented Sep 5, 2017

I'm not sure if this is possible in the fully general case (because generics can result in the instantiation of other generics by calling functions). @rjmccall would know more.

@rjmccall
Copy link
Member

rjmccall commented Sep 5, 2017

Yeah, we can't guarantee this in the most general case, but we can certainly do much better than we do today.

@phausler
Copy link
Member Author

phausler commented Sep 5, 2017

would it be possible to emit a better diagnostic than just "something failed somewhere"?

@rjmccall
Copy link
Member

rjmccall commented Sep 5, 2017

Yes, we could try to do that.

@slavapestov
Copy link
Member

@phausler This was actually mostly fixed in 4.2, with remaining work for class metadata now in swift-5.0-branch. We now support cyclic metadata, there's no need to diagnose anything 🙂

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

4 participants