Explain to me please one generic initializing error

Hello. I have next code

protocol CollectionInside {
    associatedtype Somecollection: Collection, ExpressibleByArrayLiteral
    var collection: Somecollection { get set }
}

extension CollectionInside {
    mutating func setCollection(from array: [Somecollection.Element]) {
        collection = Somecollection(arrayLiteral: array) // Non-nominal type 'Self.Somecollection' does not support explicit initialization
    }
}

I always confused with initializing protocols. And now I want to create the generic instance of Somecollection in the function setCollection(from array: [Somecollection.Element]). But it is not allowed me with an error
Non-nominal type 'Self.Somecollection' does not support explicit initialization. But why? Elements in array and in my Somecollection is same. What does Non-nominal type mean?

The ExpressibleByArrayLiteral initializer has the signature:

init(arrayLiteral elements: ArrayLiteralElement...)

So the first problem is that Somecollection.Element is not known to be the same type as Somecollection.ArrayLiteralElement.

However the second problem is that Swift does not currently provide a way to “splat” an existing array into a variadic argument list.

Here are a couple links to Swift Evolution discussions about solving that issue:

1 Like

I think you can do this if Somecollection requires RangeReplacableCollection instead (which will provide you access to the init):

protocol CollectionInside {
	associatedtype Somecollection: RangeReplaceableCollection, ExpressibleByArrayLiteral where Somecollection.Element == Somecollection.ArrayLiteralElement
    var collection: Somecollection { get set }
}

extension CollectionInside {
    mutating func setCollection(from array: [Somecollection.Element]) {
		collection = Somecollection.init(array)
    }
}
1 Like

I assembled the simple model but my initialization still does not work.

protocol LiquidSource {
    associatedtype Liquid
    func getLiquid() -> Liquid
}

protocol Plantable {
    associatedtype Resource
    init(resource: Resource)
}

protocol Meadow {
    associatedtype Item: Plantable
    associatedtype Source: LiquidSource
    var item: Item { get set }
    var source: Source { get set }
}

extension Meadow where Plantable.Resource == LiquidSource.Liquid { // Associated type 'Liquid' can only be used with a concrete type or generic parameter base
    mutating func generateItem() {
//        let recource = source.getLiquid()
//        item = Item(resource: recource)
    }
}

What's wrong with it?

You need to do extension Meadow where Item.Resource == Source.Liquid { ... }

1 Like