# Calling private methods from extensions in separate files

**URL:** <https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029>\
**Category:** Discussion\
**Created:** [December 13, 2021, 6:16pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029 "2021-12-13T18:16:25Z")\
**Posts on this page:** 11\
**Page:** 3

<div class="post-metadata">

**Author:** ![Avi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/avi/32/2962_2.png) [@Avi](https://forums.swift.org/u/Avi)\
**Post date:** [December 16, 2021, 2:10pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/41 "2021-12-16T14:10:21Z")

</div>

I'd be quite happy if extensions to a type within the module that defines the type could access private members of that type. Essentially turn `private` into the proposed `typeprivate`. Given the current alternative of forcing members to be `internal`, I don't see any downsides.

---

<div class="post-metadata">

**Author:** ![Nobody1707](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nobody1707/32/2169_2.png) [@Nobody1707](https://forums.swift.org/u/Nobody1707)\
**Post date:** [December 16, 2021, 3:06pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/42 "2021-12-16T15:06:09Z")

</div>

There's nothing wrong with (file)private functions and members used for implementing the actual interface of a type. I just believe that if you can't fit all of those in one file, then there's something wrong with your code.

---

<div class="post-metadata">

**Author:** ![Avi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/avi/32/2962_2.png) [@Avi](https://forums.swift.org/u/Avi)\
**Post date:** [December 16, 2021, 3:19pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/43 "2021-12-16T15:19:09Z")

</div>

That is way too judgmental and subjective to be a valid argument, even if it is a valid opinion.

---

<div class="post-metadata">

**Author:** ![Stan\_Smida](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stan_smida/32/10999_2.png) [@Stan\_Smida](https://forums.swift.org/u/Stan_Smida)\
**Post date:** [December 16, 2021, 3:29pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/44 "2021-12-16T15:29:34Z")

</div>

In certain cases, [Scoped Conformances](https://forums.swift.org/t/scoped-conformances/37159) could help, which seems to be [likely](https://forums.swift.org/t/improving-sendable/52377/22) implemented in the near future.

For other cases, it would be nice to have something between internal and fileprivate. I think I was there that neither a new module, nor internal access modifier felt appropriate.

But I can live without it. Scoped conformances however I really desire for!

---

<div class="post-metadata">

**Author:** ![valentinradu](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/valentinradu/32/23005_2.png) [@valentinradu](https://forums.swift.org/u/valentinradu)\
**Post date:** [December 16, 2021, 3:44pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/45 "2021-12-16T15:44:05Z")

</div>

We split code based on module responsibility, not teams or origin (third party or not). It works great and feels like `internal` is used as intended. We sometime implement protocols in an extension of types from other modules, but those should not have access to the internal members anyway, so it's a plus, keeping things tidy. And if they do, then it usually means that there's a strong overlap between modules, which usually signals a flaw in the architecture (i.e. responsibilities are not handled correctly, maybe a third module is required, etc)

---

<div class="post-metadata">

**Author:** ![valentinradu](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/valentinradu/32/23005_2.png) [@valentinradu](https://forums.swift.org/u/valentinradu)\
**Post date:** [December 16, 2021, 3:55pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/46 "2021-12-16T15:55:13Z")

</div>

> [@tera](#):
>
> The introduction of a new, say, "typeprivate" doesn't mean you have to necessarily use it or otherwise "micromanage" types' access rights, it's an opt-in.

Yeah, but it does unnecessarily bloats the language. Just because we can, it doesn't mean we should. Also, I think that implementing protocols or in general, anything in an extension should be seen as a way to add behaviour using the type's public interface, without manipulating the internal state.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [December 16, 2021, 4:27pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/47 "2021-12-16T16:27:21Z")

</div>

Well, let's explore the idea space for a moment.

For the most part, the difference between `foo(a, b)` and `a.foo(b)` is virtually non-existence, to the point that we have _"Prefer methods and properties to free functions."_ to [Swift.org - API Design Guidelines](https://www.swift.org/documentation/api-design-guidelines/#general-conventions), expecting us to be able to choose either form on the fly. We also want something between `fileprivate` and `interval`, which is the main portion of this thread. Finally, I want to throw in an extra that one would normally move the files around for refactoring, so it should support that too.

Putting the requirements together, the feature should

1. Work well for both `a.foo(b)` and `foo(a, b)` forms,
2. Be between `fileprivate` and `internal`,
3. Require minimal changes when moving files around.

Now, access control normally means _you can use X so long as you have the same Y_. For `fileprivate` and `internal`, `Y`s are "the containing file" and "containing module", respectively.

For `typeprivate` idea, `Y` is "the type that owns the function". So they would fail (1) but pass the other two.

Another idea is to have `folder` level access control, which would fail (3) but pass (1) and (2).

Finally, since neither `typeprivate` nor `folder` exactly fits the bill, maybe we can create our own `Y`. Let's name them, IDK, `namespace`, which can be declared as needed. The idea is that you declare a `namespace` somewhere in the module, then use it to identify the access control level (between `private` and `internal`) as needed. When you need to use anything from inside the namespace, you can then `import` it (parallel the idea that namespace is a _mini-module_).

```swift
// A.swift
namespace Namespace1

struct X {
  protected(Namespace1) func foo() { .. }
}
protected(Namespace1) func foo() { .. }

// B.swift
private func bar() { foo() /* fail */ }

// C.swift
import namespace Namespace1
private func bar() { foo() /* ok */ }

```

This would pass all the requirements, and should pretty much work for your problem as well.

* * *

> [@tera](#):
>
> The introduction of a new, say, "typeprivate" doesn't mean you have to necessarily use it or otherwise "micromanage" types' access rights, it's an opt-in.

I can never appreciate the "opt-in" argument. For sure, I can just opt out of the feature on my own, but what if I am part of a bigger team? I guess I can negotiate. What if I want to contribute to an opensource that opts in? What if someone wants to contribute to my open-source project and wants to opt-in? This argument only works when you live in a vacuum. We don't. I either leave or stay with the codebase that uses it, much to my own detriments.

Furthermore, it's dismissive and very disengaging. It says at least as much as

- "I agree that it's a problem, but"
- "I'm not going to do anything about it."

If it's not that big of a problem, convince me. If it can be alleviated, please do so. Such an answer doesn't move the conversation forward and simply leaves me out of the equation.

You could even say that I can still work around that by bypassing the type on my own. It's much easier for Swift as you can add any function to any type:

```swift
struct X {
  func bypass() { X.typeprivateFunction() }
}

func foo() { X.typeprivateFunction() /* bad */ }
func bar() { X.bypass() /* ok */ }

```

This is not ideal, but at the very least doesn't bar me from having the API I want. Even I, who is a skeptic of `typeprivate`, can come up with that much. I'd expect at least this much, or at least, anything better than _"Just don't use it"_.

* * *

Now, I'm not claiming the ideas to be good or anything (and `folder` is just an old idea others have pitched). Both `folder` and `namespace` ideas would also have implementation hurdles to overcome, and one can reasonably come up with entirely different sets of requirements from me. That said, at the very least, I really wish we would at least take a deeper look before both sides start being defensive of their own champions.

* * *

I'll probably go and cool off from this thread a little bit. I came in expecting some new stuff on the table given there are a few new faces here, but it seems to end up much the same.

---

<div class="post-metadata">

**Author:** ![anon9791410](https://avatars.discourse-cdn.com/v4/letter/a/9fc348/32.png) [@anon9791410](https://forums.swift.org/u/anon9791410)\
**Post date:** [December 16, 2021, 4:36pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/48 "2021-12-16T16:36:09Z")

</div>

> [@xwu](#):
>
> Swift’s access modifiers are deliberately _lexical_, not _type-based_. The access modifier that allows use throughout a module is `internal`, within a file `fileprivate`, and within a _lexical_ scope `private`.
> 
> Other languages may offer type-based access modifiers, but that is deliberately not the case for Swift.

This is inaccurate for `private`, which is a hybrid.

`private` in Swift actually means `fileprotected`. I.e. the same as `protected`, but invisible to other files.

And `fileprivate` would be better expressed as `fileinternal`.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [December 16, 2021, 5:18pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/49 "2021-12-16T17:18:28Z")

</div>

> [@Lantua](#):
>
> I can never appreciate the "opt-in" argument. For sure, I can just opt out of the feature on my own, but what if I am part of a bigger team? I guess I can negotiate. What if I want to contribute to an opensource that opts in? What if someone wants to contribute to my open-source project and wants to opt-in? This argument only works when you live in a vacuum. We don't. I either leave or stay with the codebase that uses it, much to my own detriments.
> 
> Furthermore, it's dismissive and very disengaging. It says at least as much as
> 
> - "I agree that it's a problem, but"
> - "I'm not going to do anything about it."
> 
> If it's not that big of a problem, convince me. If it can be alleviated, please do so. Such an answer doesn't move the conversation forward and simply leaves me out of the equation.

I will review your folder/namespace ideas later on. A quick meta comment now about the above. I can well appreciate yout point. At the end of the day either one camp is coerced to the other camp's preference or there is a language fragmentation, either not ideal. The "don't use access levels if you don't want them" argument is probably a semi-emotional response to the other camp's claims that "1. there is no problem to solve". and "2. if there is a problem just use ~~the heavy artillery~~ modules".

---

<div class="post-metadata">

**Author:** ![Dante-Broggi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dante-broggi/32/7955_2.png) [@Dante-Broggi](https://forums.swift.org/u/Dante-Broggi)\
**Post date:** [December 16, 2021, 6:19pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/50 "2021-12-16T18:19:21Z")

</div>

One thing I have mentioned [previously](https://forums.swift.org/t/a-level-of-access-control-between-fileprivate-and-internal-for-code-partitioning/37178/2) in terms of finer grained access control is for Swift to clone and modify Rust's module system as "small `mod`ules", with a new access control level `external`.

That is add a `mod` concept which in some manner groups files together in a new unit.  
All old "large" modules contain a single implicit "small" module.  
New "large" modules can contain several "small" modules

This means changing the meaning of `internal` to be within the smallest containing `mod` is not source breaking (I think), thus `external` could be a new access control level which is either equivalent to the old `internal` (all files in the "large Module") or just all files in the/any parent `mod`.

---

<div class="post-metadata">

**Author:** ![Ling\_Wang](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ling_wang/32/2691_2.png) [@Ling\_Wang](https://forums.swift.org/u/Ling_Wang)\
**Post date:** [August 23, 2025, 1:05pm UTC](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029/51 "2025-08-23T13:05:17Z")

</div>

So what’s the conclusion?

1. Keeping private things private but accept huge files
2. Or, exposing private things as internal to break down classes into extensions in different files?

I hope there is a private-in-type-in-same-module access level, but accepting that we don’t have that I’m curious to learn what others chose as a workaround.

[Previous page](https://forums.swift.org/t/calling-private-methods-from-extensions-in-separate-files/54029.md?page=2)
