Calling a function for each element of an array of mixed elements conforming to a same protocol

I am trying to call a function for each element of an array of mixed elements conforming to a same protocol.

Please consider the following code, the export and exportA compile fine but as soon as I add a requirement that Database inherits from a class then exportB won't compile.
My first assumption is that everything below should compile but maybe there's something more than I don't get.

So, what am I doing wrong and is there any way to make it work with a class inheritance constraint ?
Thanks

protocol DatabaseExporter<Database> {
	associatedtype Database
	
	func export(database: Database)
}

func export<Database>(database: Database, usingExporters exporters: [any DatabaseExporter<Database>]) {
	for exporter in exporters {
		exporter.export(database: database)
	}
}

protocol A {}

func exportA<Database: A>(database: Database, usingExporters exporters: [any DatabaseExporter<Database>]) {
	for exporter in exporters {
		exporter.export(database: database)
	}
}

class B {}

func exportB<Database: B>(database: Database, usingExporters exporters: [any DatabaseExporter<Database>]) {
	for exporter in exporters {
		exporter.export(database: database) /// Error : Member 'export' cannot be used on value of type 'any DatabaseExporter<Database>'; consider using a generic constraint instead
		exportB(database: database, usingExporter: exporter) /// Error : Global function 'exportB(database:usingExporter:)' requires that 'Database' inherit from 'B'
	}
}

func exportB<Database: B>(database: Database, usingExporter exporter: some DatabaseExporter<Database>) {
	exporter.export(database: database)
}
1 Like

The simple change fixes the compile issue:

protocol C: DatabaseExporter where Database : B { }

(And change the generic type constraint in the two exportB funcs from B to C)

I'm not sure why your code don't work, but is subclass a valid generic constraint? (I seldom use class in my own code, I'm just curious if your have a reference).

This is a bug. Please file a bug report at Issues · apple/swift · GitHub.

Ok thanks for taking a look at my problem. I just submitted a new issue, #67198 for the record.

Perhaps I misunderstood your advice but changing exportB<Database: B> to exportB<Database: C> is not what I want because Database is not meant to be a DatabaseExporter.

Sorry, my mistake. I think a workaround is to define a protocol for base class B and modify the constraints in both exportB funcs to conform to that protocol.