It turns out that the “private access level” complaint was regarding the initializer, not the struct. The initializer’s access level is only as accessible as the least accessible instance variable.
If I make the string instance variable anything other than private, the error goes away:
private struct A {
let string: String
// synthesized initializer:
// init(string: String)
}
So given that B can now read A‘s string, it can also access A‘s initializer.
If A had another private property though, then again its initializer would become private:
private struct A {
let string: String
private let int: Int
// synthesized initializer:
// private init(string: String, int: Int)
...
}