Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redundant duplication of typealiase declarations when conforms to a protocol (Part 2)

protocol Destinationable: Hashable {
    associatedtype D: Hashable
    var destination: D { get }
}

protocol Graph {
    associatedtype Edge: Destinationable
    subscript(node: D) -> Set<Edge>! { get set }
}

extension Graph {
    typealias D = Edge.D
}

struct UndirectedGraph<Edge: Destinationable>: Graph {
    typealias D = Edge.D // Why should we again declare this typealias!?
    
    private var storage: [D: Set<Edge>]
    
    subscript(node: D) -> Set<Edge>! {
        get { storage[node] }
        set { storage[node] = newValue }
    }
}

This works. But if I remove redeclaration of typealias D = Edge.D in the struct I get an compilation error, related to the subscript:

Unsupported recursion for reference to type alias 'D' of type 'UndirectedGraph'

Why is it happening? What recursion???

like image 413
Roman Avatar asked Nov 07 '22 04:11

Roman


1 Answers

I'm not sure what recursion, but you should avoid declaring typealiases in protocol extensions and use same-type constaints instead:

protocol Destinationable: Hashable {
    associatedtype D: Hashable
    var destination: D { get }
}

protocol Graph {
    associatedtype D
    associatedtype Edge: Destinationable where D == Edge.D
    subscript(node: D) -> Set<Edge>! { get set }
}

struct UndirectedGraph<Edge: Destinationable>: Graph {
    private var storage: [D: Set<Edge>]
    
    subscript(node: Edge.D) -> Set<Edge>! {
        get { storage[node] }
        set { storage[node] = newValue }
    }
}

compiles just fine but in your case:

protocol Destinationable: Hashable {
    associatedtype D: Hashable
    var destination: D { get }
}

protocol Graph {
    associatedtype Edge: Destinationable
    subscript(node: Edge.D) -> Set<Edge>! { get set }
}

struct UndirectedGraph<Edge: Destinationable>: Graph {
    private var storage: [Edge.D: Set<Edge>]
    
    subscript(node: Edge.D) -> Set<Edge>! {
        get { storage[node] }
        set { storage[node] = newValue }
    }
}

might be enough.

like image 174
AnderCover Avatar answered Dec 20 '22 06:12

AnderCover