Namespacing protocols to other types

I have tweaked the type checker to allow that. I have also tweaked getContextSubstitutions() to substitute the types, although I am not sure if I have done that correctly.

protocol A {
  struct B {}

Inside IRGen, dumping the struct gives:

struct_decl range=[/Users/suyashsrijan/Desktop/test.swift:2:3 - line:2:13] "B" interface type='A.B.Type' access=internal non-resilient
  (constructor_decl implicit range=[/Users/suyashsrijan/Desktop/test.swift:2:10 - line:2:10] "init()" interface type='<Self where Self : A> (A.B.Type) -> () -> A.B' access=internal designated
    (parameter "self" interface type='A.B' inout)
    (brace_stmt implicit
      (return_stmt implicit))))

I have also put emitNestedTypeDecls(protocol->getMembers()) inside emitProtocolDecl, however it has trouble emitting the metadata for the struct (crashes in type converter). If you change the struct to a class, then the crash is in useConformance (because the protocol conformance ref is invalid).

Seems like I am missing something or the type substitution isn't working correctly.

The type of 'self' inside a method of A.B must not be A.B, but Self.B where Self is the outer type parameter from the protocol A. However NominalType cannot model that right now.

I think a first step would be the planned changes to unify BoundGenericNominalType and NominalType, and change BoundGenericNominalType to store a substitution map instead of an array of generic arguments together with a parent type. Then the requisite changes to handle substitutions would be trivial.

1 Like

Hmm when will the planned changes happen? Is it worth waiting or could we just go with nested protocols first and build upon it later?

I don't think there are any concrete plans yet, but if you're interested, merging NominalType into BoundGenericNominalType would be a good first step.

And yeah, I think nesting protocols inside non-generic concrete types is much easier than the other direction and should not require any major representational changes.


This proposal has all our hearts desires about nesting protocols and the reverse: Ease restrictions on protocol nesting by karwa · Pull Request #552 · apple/swift-evolution · GitHub

Unfortunately it hasn't moved since Swift 3, even though everyone seems to agree about it there. I don't know why it was closed either for no good reason. Can we re-open it and push it along further?

Hi @Karl, your PR hasn‘t moved forward for several month. I wonder if you still intend to push it forward or would you like someone else to take over it (maybe @suyashsrijan)?!

Thank you for the update in advance.

I have something working, just need to write some tests. I’ll try to do that in the next few days.

It’s pretty basic - just putting protocols inside other types, but that’s a good start and would be nice to get it merged first before we think about putting other types inside protocols (esp. since its related to generic protocols).


That is still great news. Looking forward to it.


Is this topic dead ? I still have the need for namespacing everytime my project starts to reach a certain size.

1 Like

Everyone does. But any discussion inevitably sinks in "but what should we do with generics?" or something like that.

Modules already provide a good solution to namespacing.

If that's true then why are there so many uninhabited enums used as namespaces floating around?


They actually provide a fairly terrible solution. The only time they perform adequately is when using someone else's module. When writing your own (your app is a single module, by default), you might find that namespacing is useful for organization purposes, but that the overhead of a module is not worth the cost. This usually leads to language hacks such as uninhabited enums.

Personally, I have come across many instances where I had a collection of related static functions with which I did not want to pollute the global namespace. Also, I wanted it clear that the functions are indeed related. So I use uninhabited enums. I'm not going to create a module for half-a-dozen or fewer functions.


Currently the best hack to allow nesting protocols inside of other types is to use a typealias. So given the common MyView.Delegate use-case, you could write something like:

protocol _MyViewDelegate: AnyObject {

struct MyView {
  typealias Delegate = _MyViewDelegate

class SomeDelegate: MyView.Delegate { // works!

But yeah, it would be a lot nicer if we could write that the way we write other nested types. I also still really want nested types in protocols.


Karl's example has nothing to do with my use case, and your pejorative is unwarranted.


This looks like an excellent suggestion to me, cc: @Avi!