Pitch: Protocols with private fields

Perhaps you misunderstood my pitch.

First, let me stress that I agree with your premise:

We disagree on the conclusion:

Currently, a protocol prescribes that all its requirements have at least the same access level as the whole conforming type. You can (although that's probably useless) implement the requirement with a higher access level. So, in fact, requirements have a lower bound defined by that of the protocol's access level.

The heart of my pitch is to let allow protocols to specify other lower bounds on individual requirements.

So, in your example, fileprivate would have a different meaning than in the context of a standard type declaration. It would indicate that conforming types should at least provide a fileprivate implementation of that requirement. Consumers of the protocol would not be allowed to expect the requirement to be visible, unless they are declared in the same file as the protocol.

// in P.swift
public protocol P {
  var foo: Int { get fileprivate(set) }
  var bar: Int { get private(set) }
}

// In S.swift
public struct S: P {
  public internal(set) var foo: Int
  public fileprivate(set) var bar: Int
}

// In main.swift (same module)
let s = S(foo: 1, bar: 2)
print(s.foo) // OK, getter is public
s.foo = 3    // OK, setter is internal
s.bar = 3    // Error, setter is fileprivate

let p: P = s
print(p.foo) // OK, getter must be at least public
p.foo = 3    // Error, getter might be as low as fileprivate
p.bar = 3    // Error, getter might be as low as private

Notice that the conforming type is allowed to choose the access level with which it wants to expose its requirements, as long as they are higher than what the protocol prescribes.

internal protocol Q {
  var foo: Int { get set }
}

// The extension is well-typed because S chose to expose
// foo's setter as internal.
extension S: Q {}

What the conforming type cannot do is to implement the requirement with a lower access level than prescribed, as it would violate the assumptions that consumers of the protocol can make.

struct T: P {
  private var foo: Int // Error, `foo` must be a least fileprivate
}

I believe that we could encapsulate behavior in default implementations using that approach. I provided an example in the original post. I'll add another based on your example as template:

// in Q.swfit
public protocol Q {
  var foo: Int { private(get) private(set) }
}

extension Q {
  public mutating count() -> Int {
    foo += 1 // OK, a type can always access its own
             // properties regardless of their access level
    return foo
  }
}

// In U.swift
public struct U: Q {
  // foo is invisible to the consumers of this type
  private var foo: Int = 0
}

// In main.swift
var q: Q = U()
print(q.foo)     // Error, getter might be as low as fileprivate
print(q.count()) // OK, prints 1
print(q.count()) // OK, prints 2